feat(backend): Add local local

This commit is contained in:
2026-06-13 09:09:53 +08:00
parent 09a99bbc33
commit 2d87760c79
2 changed files with 54 additions and 46 deletions
+9 -7
View File
@@ -19,6 +19,7 @@ pub enum ARMInstr{
Bl(BlInstr), Bl(BlInstr),
B(BInstr), B(BInstr),
Label(String), Label(String),
LocalLabel(String),
} }
impl Display for ARMInstr { impl Display for ARMInstr {
@@ -41,6 +42,7 @@ impl Display for ARMInstr {
ARMInstr::B(instr) => write!(f, "{}", instr), ARMInstr::B(instr) => write!(f, "{}", instr),
ARMInstr::FunctionHead(name, align_size) => write!(f, ".align {}\n.global {}\n.type {}, %function\n{}:", align_size, name, name, name), ARMInstr::FunctionHead(name, align_size) => write!(f, ".align {}\n.global {}\n.type {}, %function\n{}:", align_size, name, name, name),
ARMInstr::Label(name) => write!(f, "{}:", name), ARMInstr::Label(name) => write!(f, "{}:", name),
ARMInstr::LocalLabel(name) => write!(f, "{}:", name),
} }
} }
} }
@@ -132,7 +134,7 @@ impl Display for MoveInstr {
pub enum MoveWideOperand { pub enum MoveWideOperand {
Imm(u16), Imm(u16),
Symbol(String), Symbol(String, String),
} }
pub struct MovwInstr(Register, MoveWideOperand); pub struct MovwInstr(Register, MoveWideOperand);
@@ -141,8 +143,8 @@ impl MovwInstr {
ARMInstr::Movw(MovwInstr(dest, MoveWideOperand::Imm(value))) ARMInstr::Movw(MovwInstr(dest, MoveWideOperand::Imm(value)))
} }
pub fn new_symbol(dest: Register, name: String) -> ARMInstr { pub fn new_symbol(dest: Register, name: String, anchor: String) -> ARMInstr {
ARMInstr::Movw(MovwInstr(dest, MoveWideOperand::Symbol(name))) ARMInstr::Movw(MovwInstr(dest, MoveWideOperand::Symbol(name, anchor)))
} }
} }
impl Display for MovwInstr { impl Display for MovwInstr {
@@ -150,7 +152,7 @@ impl Display for MovwInstr {
let MovwInstr(dest, operand) = self; let MovwInstr(dest, operand) = self;
match operand { match operand {
MoveWideOperand::Imm(value) => write!(f, "movw {}, #{}", dest, value), MoveWideOperand::Imm(value) => write!(f, "movw {}, #{}", dest, value),
MoveWideOperand::Symbol(name) => write!(f, "movw {}, #:lower16:{}", dest, name), MoveWideOperand::Symbol(name, anchor) => write!(f, "movw {}, #:lower16:{}-({}+8)", dest, name, anchor),
} }
} }
} }
@@ -161,8 +163,8 @@ impl MovtInstr {
ARMInstr::Movt(MovtInstr(dest, MoveWideOperand::Imm(value))) ARMInstr::Movt(MovtInstr(dest, MoveWideOperand::Imm(value)))
} }
pub fn new_symbol(dest: Register, name: String) -> ARMInstr { pub fn new_symbol(dest: Register, name: String, anchor: String) -> ARMInstr {
ARMInstr::Movt(MovtInstr(dest, MoveWideOperand::Symbol(name))) ARMInstr::Movt(MovtInstr(dest, MoveWideOperand::Symbol(name, anchor)))
} }
} }
impl Display for MovtInstr { impl Display for MovtInstr {
@@ -170,7 +172,7 @@ impl Display for MovtInstr {
let MovtInstr(dest, operand) = self; let MovtInstr(dest, operand) = self;
match operand { match operand {
MoveWideOperand::Imm(value) => write!(f, "movt {}, #{}", dest, value), MoveWideOperand::Imm(value) => write!(f, "movt {}, #{}", dest, value),
MoveWideOperand::Symbol(name) => write!(f, "movt {}, #:upper16:{}", dest, name), MoveWideOperand::Symbol(name, anchor) => write!(f, "movt {}, #:upper16:{}-({}+8)", dest, name, anchor),
} }
} }
} }
+45 -39
View File
@@ -1,6 +1,6 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use crate::{backend::{arm_instr::{ARMInstr, AddInstr, BInstr, BlInstr, CmpInstr, ConditionCode, LoadInstr, MoveInstr, MovtInstr, MovwInstr, MulInstr, PopInstr, PushInstr, RegisterOrImm, RsbInstr, SDivInstr, StoreInstr, SubInstr}, register_allocator::{REG_FP, REG_R0, REG_R1, REG_R2, REG_R3, REG_SP, Register, RegisterAlloc, RegisterAllocator}, types::ARMAsmVar}, ir::types::{Function, IRInstr, MoveRValue, Variable, VariableOrIntLit, VariableType}}; use crate::{backend::{arm_instr::{ARMInstr, AddInstr, BInstr, BlInstr, CmpInstr, ConditionCode, LoadInstr, MoveInstr, MovtInstr, MovwInstr, MulInstr, PopInstr, PushInstr, RegisterOrImm, RsbInstr, SDivInstr, StoreInstr, SubInstr}, register_allocator::{REG_FP, REG_PC, REG_R0, REG_R1, REG_R2, REG_R3, REG_SP, Register, RegisterAlloc, RegisterAllocator}, types::ARMAsmVar}, ir::types::{Function, IRInstr, MoveRValue, Variable, VariableOrIntLit, VariableType}};
use crate::ir::types::BinaryOp as IRBinaryOp; use crate::ir::types::BinaryOp as IRBinaryOp;
use crate::ir::types::CmpOp as IRCmpOp; use crate::ir::types::CmpOp as IRCmpOp;
use crate::ir::types::UnaryOp as IRUnaryOp; use crate::ir::types::UnaryOp as IRUnaryOp;
@@ -11,6 +11,7 @@ pub struct Generator {
var_inited: Vec<ARMAsmVar>, var_inited: Vec<ARMAsmVar>,
var_uninited: Vec<ARMAsmVar>, var_uninited: Vec<ARMAsmVar>,
register_allocator: RegisterAllocator, register_allocator: RegisterAllocator,
symbol_addr_label_counter: usize,
} }
const DEFAULT_VAR_ALIGN: usize = 4; const DEFAULT_VAR_ALIGN: usize = 4;
@@ -30,11 +31,6 @@ fn emit_load_imm32(dest: Register, value: i32, instrs: &mut Vec<ARMInstr>) {
} }
} }
fn emit_load_symbol_addr(dest: Register, name: String, instrs: &mut Vec<ARMInstr>) {
instrs.push(MovwInstr::new_symbol(dest, name.clone()));
instrs.push(MovtInstr::new_symbol(dest, name));
}
fn emit_sub_imm(dest: Register, left: Register, imm: i32, instrs: &mut Vec<ARMInstr>) { fn emit_sub_imm(dest: Register, left: Register, imm: i32, instrs: &mut Vec<ARMInstr>) {
if imm == 0 { if imm == 0 {
if dest != left { if dest != left {
@@ -91,33 +87,34 @@ fn emit_store_stack(src: Register, offset: i32, reg_allocator: &mut RegisterAllo
} }
} }
fn load_variable(variable: Variable, reg_allocator: &mut RegisterAllocator, var_index_to_stack_offset: &BTreeMap<usize, usize>, instrs: &mut Vec<ARMInstr>) -> RegisterAlloc { fn load_variable(variable: Variable, generator: &mut Generator, var_index_to_stack_offset: &BTreeMap<usize, usize>) -> RegisterAlloc {
let reg_allocator = &mut generator.register_allocator;
if variable.data_type.is_array() { if variable.data_type.is_array() {
let var_alloc = reg_allocator.alloc(variable.clone()).expect("Ran out of registers"); let var_alloc = reg_allocator.alloc(variable.clone()).expect("Ran out of registers");
if variable.data_type.is_array_param() { if variable.data_type.is_array_param() {
match variable.var_type { match variable.var_type {
VariableType::ParamTemp(param_index) => { VariableType::ParamTemp(param_index) => {
if param_index < ARG_REGS.len() { if param_index < ARG_REGS.len() {
instrs.push(MoveInstr::new_uncond(var_alloc.reg, RegisterOrImm::Reg(ARG_REGS[param_index]))); generator.instrs.push(MoveInstr::new_uncond(var_alloc.reg, RegisterOrImm::Reg(ARG_REGS[param_index])));
} else { } else {
let stack_arg_offset = 8 + ((param_index - ARG_REGS.len()) * 4); let stack_arg_offset = 8 + ((param_index - ARG_REGS.len()) * 4);
instrs.push(LoadInstr::new(var_alloc.reg, REG_FP, Some(RegisterOrImm::Imm(stack_arg_offset as i32)))); generator.instrs.push(LoadInstr::new(var_alloc.reg, REG_FP, Some(RegisterOrImm::Imm(stack_arg_offset as i32))));
} }
} }
_ => { _ => {
let stack_offset = var_index_to_stack_offset.get(&variable.index).expect("Variable not declared"); let stack_offset = var_index_to_stack_offset.get(&variable.index).expect("Variable not declared");
emit_load_stack(var_alloc.reg, *stack_offset as i32, reg_allocator, instrs); emit_load_stack(var_alloc.reg, *stack_offset as i32, &mut generator.register_allocator, &mut generator.instrs);
} }
} }
return var_alloc; return var_alloc;
} }
match variable.var_type { match variable.var_type {
VariableType::Global => { VariableType::Global => {
emit_load_symbol_addr(var_alloc.reg, format!("global_var_{}", variable.index), instrs); generator.emit_load_symbol_addr(var_alloc.reg, format!("global_var_{}", variable.index));
} }
_ => { _ => {
let stack_offset = var_index_to_stack_offset.get(&variable.index).expect("Variable not declared"); let stack_offset = var_index_to_stack_offset.get(&variable.index).expect("Variable not declared");
emit_sub_imm(var_alloc.reg, REG_FP, *stack_offset as i32, instrs); emit_sub_imm(var_alloc.reg, REG_FP, *stack_offset as i32, &mut generator.instrs);
} }
} }
return var_alloc; return var_alloc;
@@ -128,8 +125,8 @@ fn load_variable(variable: Variable, reg_allocator: &mut RegisterAllocator, var_
let var_reg = var_alloc.reg; let var_reg = var_alloc.reg;
// if !var_alloc.is_reused { // if !var_alloc.is_reused {
let address_alloc = reg_allocator.alloc_any().expect("Ran out of registers"); let address_alloc = reg_allocator.alloc_any().expect("Ran out of registers");
emit_load_symbol_addr(address_alloc.reg, format!("global_var_{}", variable.index), instrs); generator.emit_load_symbol_addr(address_alloc.reg, format!("global_var_{}", variable.index));
instrs.push(LoadInstr::new(var_reg, address_alloc.reg, None)); generator.instrs.push(LoadInstr::new(var_reg, address_alloc.reg, None));
// } // }
var_alloc var_alloc
}, },
@@ -141,7 +138,7 @@ fn load_variable(variable: Variable, reg_allocator: &mut RegisterAllocator, var_
} else { } else {
let var_alloc = reg_allocator.alloc(variable.clone()).expect("Ran out of registers"); let var_alloc = reg_allocator.alloc(variable.clone()).expect("Ran out of registers");
let stack_arg_offset = 8 + ((param_index - ARG_REGS.len()) * 4); let stack_arg_offset = 8 + ((param_index - ARG_REGS.len()) * 4);
instrs.push(LoadInstr::new(var_alloc.reg, REG_FP, Some(RegisterOrImm::Imm(stack_arg_offset as i32)))); generator.instrs.push(LoadInstr::new(var_alloc.reg, REG_FP, Some(RegisterOrImm::Imm(stack_arg_offset as i32))));
var_alloc var_alloc
} }
}, },
@@ -149,26 +146,26 @@ fn load_variable(variable: Variable, reg_allocator: &mut RegisterAllocator, var_
let stack_offset = var_index_to_stack_offset.get(&variable.index).expect("Variable not declared"); let stack_offset = var_index_to_stack_offset.get(&variable.index).expect("Variable not declared");
let var_alloc = reg_allocator.alloc(variable.clone()).expect("Ran out of registers"); let var_alloc = reg_allocator.alloc(variable.clone()).expect("Ran out of registers");
// if !var_alloc.is_reused { // if !var_alloc.is_reused {
emit_load_stack(var_alloc.reg, *stack_offset as i32, reg_allocator, instrs); emit_load_stack(var_alloc.reg, *stack_offset as i32, &mut generator.register_allocator, &mut generator.instrs);
// } // }
var_alloc var_alloc
} }
} }
} }
fn save_variable(variable: Variable, reg: Register, reg_allocator: &mut RegisterAllocator, var_index_to_stack_offset: &BTreeMap<usize, usize>, instrs: &mut Vec<ARMInstr>) { fn save_variable(variable: Variable, reg: Register, generator: &mut Generator, var_index_to_stack_offset: &BTreeMap<usize, usize>) {
match variable.var_type { match variable.var_type {
VariableType::Global => { VariableType::Global => {
let address_alloc = reg_allocator.alloc_any().expect("Ran out of registers"); let address_alloc = generator.register_allocator.alloc_any().expect("Ran out of registers");
emit_load_symbol_addr(address_alloc.reg, format!("global_var_{}", variable.index), instrs); generator.emit_load_symbol_addr(address_alloc.reg, format!("global_var_{}", variable.index));
instrs.push(StoreInstr::new(reg, address_alloc.reg, None)); generator.instrs.push(StoreInstr::new(reg, address_alloc.reg, None));
}, },
VariableType::ParamTemp(_) => { VariableType::ParamTemp(_) => {
todo!() todo!()
}, },
_ => { _ => {
let stack_offset = var_index_to_stack_offset.get(&variable.index).expect("Variable not declared"); let stack_offset = var_index_to_stack_offset.get(&variable.index).expect("Variable not declared");
emit_store_stack(reg, *stack_offset as i32, reg_allocator, instrs); emit_store_stack(reg, *stack_offset as i32, &mut generator.register_allocator, &mut generator.instrs);
} }
} }
} }
@@ -179,8 +176,17 @@ impl Generator {
var_inited: Vec::new(), var_inited: Vec::new(),
var_uninited: Vec::new(), var_uninited: Vec::new(),
register_allocator: RegisterAllocator::new(), register_allocator: RegisterAllocator::new(),
symbol_addr_label_counter: 0,
} }
} }
fn emit_load_symbol_addr(&mut self, dest: Register, name: String) {
let anchor = format!(".Laddr_{}", self.symbol_addr_label_counter);
self.symbol_addr_label_counter += 1;
self.instrs.push(MovwInstr::new_symbol(dest, name.clone(), anchor.clone()));
self.instrs.push(MovtInstr::new_symbol(dest, name, anchor.clone()));
self.instrs.push(ARMInstr::LocalLabel(anchor));
self.instrs.push(AddInstr::new(dest, REG_PC, RegisterOrImm::Reg(dest)));
}
pub fn emit(&mut self, ir_instrs: Vec<IRInstr>) { pub fn emit(&mut self, ir_instrs: Vec<IRInstr>) {
for ir_instr in ir_instrs { for ir_instr in ir_instrs {
match ir_instr { match ir_instr {
@@ -239,7 +245,7 @@ impl Generator {
if let Some(v) = v { if let Some(v) = v {
let ret_alloc = self.register_allocator.alloc_reg(REG_R0).expect("Ran out of registers"); let ret_alloc = self.register_allocator.alloc_reg(REG_R0).expect("Ran out of registers");
let ret_reg = ret_alloc.reg; let ret_reg = ret_alloc.reg;
let v_alloc = load_variable(v, &mut self.register_allocator, &var_index_to_stack_offset, &mut self.instrs); let v_alloc = load_variable(v, self, &var_index_to_stack_offset);
self.instrs.push(MoveInstr::new_uncond(ret_reg, RegisterOrImm::Reg(v_alloc.reg))); self.instrs.push(MoveInstr::new_uncond(ret_reg, RegisterOrImm::Reg(v_alloc.reg)));
} }
self.instrs.push(MoveInstr::new_fp_to_sp()); self.instrs.push(MoveInstr::new_fp_to_sp());
@@ -265,7 +271,7 @@ impl Generator {
IRInstr::Unary(variable, unary_op, variable1) => self.emit_unary(variable, unary_op, variable1, &var_index_to_stack_offset), IRInstr::Unary(variable, unary_op, variable1) => self.emit_unary(variable, unary_op, variable1, &var_index_to_stack_offset),
IRInstr::Goto(index) => self.instrs.push(BInstr::new(format!("label_{}_{}", func_name, index))), IRInstr::Goto(index) => self.instrs.push(BInstr::new(format!("label_{}_{}", func_name, index))),
IRInstr::CondGoto(variable, true_label_index, false_label_index) => { IRInstr::CondGoto(variable, true_label_index, false_label_index) => {
let variable_alloc = load_variable(variable, &mut self.register_allocator, &var_index_to_stack_offset, &mut self.instrs); let variable_alloc = load_variable(variable, self, &var_index_to_stack_offset);
let variable_reg = variable_alloc.reg; let variable_reg = variable_alloc.reg;
self.instrs.push(CmpInstr::new(variable_reg, RegisterOrImm::Imm(0))); self.instrs.push(CmpInstr::new(variable_reg, RegisterOrImm::Imm(0)));
self.instrs.push(BInstr::new_cond(ConditionCode::Ne, format!("label_{}_{}", func_name, true_label_index))); self.instrs.push(BInstr::new_cond(ConditionCode::Ne, format!("label_{}_{}", func_name, true_label_index)));
@@ -277,19 +283,19 @@ impl Generator {
} }
} }
fn emit_unary(&mut self, dest: Variable, unary_op: IRUnaryOp, variable: Variable, var_index_to_stack_offset: &BTreeMap<usize, usize>) { fn emit_unary(&mut self, dest: Variable, unary_op: IRUnaryOp, variable: Variable, var_index_to_stack_offset: &BTreeMap<usize, usize>) {
let variable_alloc = load_variable(variable, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); let variable_alloc = load_variable(variable, self, var_index_to_stack_offset);
let dest_alloc = self.register_allocator.alloc(dest.clone()).expect("Ran out of registers"); let dest_alloc = self.register_allocator.alloc(dest.clone()).expect("Ran out of registers");
match unary_op { match unary_op {
IRUnaryOp::Neg => { IRUnaryOp::Neg => {
self.instrs.push(RsbInstr::new(dest_alloc.reg, variable_alloc.reg, RegisterOrImm::Imm(0))); self.instrs.push(RsbInstr::new(dest_alloc.reg, variable_alloc.reg, RegisterOrImm::Imm(0)));
}, },
} }
save_variable(dest, dest_alloc.reg, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); save_variable(dest, dest_alloc.reg, self, var_index_to_stack_offset);
} }
fn emit_cmp(&mut self, variable: Variable, left: VariableOrIntLit, cmp_op: IRCmpOp, right: VariableOrIntLit, var_index_to_stack_offset: &BTreeMap<usize, usize>) { fn emit_cmp(&mut self, variable: Variable, left: VariableOrIntLit, cmp_op: IRCmpOp, right: VariableOrIntLit, var_index_to_stack_offset: &BTreeMap<usize, usize>) {
let left_alloc = match left { let left_alloc = match left {
VariableOrIntLit::Var(var) => { VariableOrIntLit::Var(var) => {
load_variable(var, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs) load_variable(var, self, var_index_to_stack_offset)
}, },
VariableOrIntLit::IntLit(lit) => { VariableOrIntLit::IntLit(lit) => {
let alloc = self.register_allocator.alloc_any().expect("Ran out of registers"); let alloc = self.register_allocator.alloc_any().expect("Ran out of registers");
@@ -300,7 +306,7 @@ impl Generator {
// TODO: check left == right // TODO: check left == right
let right_alloc = match right { let right_alloc = match right {
VariableOrIntLit::Var(var) => { VariableOrIntLit::Var(var) => {
load_variable(var, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs) load_variable(var, self, var_index_to_stack_offset)
}, },
VariableOrIntLit::IntLit(lit) => { VariableOrIntLit::IntLit(lit) => {
let alloc = self.register_allocator.alloc_any().expect("Ran out of registers"); let alloc = self.register_allocator.alloc_any().expect("Ran out of registers");
@@ -313,7 +319,7 @@ impl Generator {
self.instrs.push(CmpInstr::new(left_alloc.reg, RegisterOrImm::Reg(right_alloc.reg))); self.instrs.push(CmpInstr::new(left_alloc.reg, RegisterOrImm::Reg(right_alloc.reg)));
self.instrs.push(MoveInstr::new_uncond(variable_reg, RegisterOrImm::Imm(0))); self.instrs.push(MoveInstr::new_uncond(variable_reg, RegisterOrImm::Imm(0)));
self.instrs.push(MoveInstr::new_cond(cmp_op.into(), variable_reg, RegisterOrImm::Imm(1))); self.instrs.push(MoveInstr::new_cond(cmp_op.into(), variable_reg, RegisterOrImm::Imm(1)));
save_variable(variable, variable_alloc.reg, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); save_variable(variable, variable_alloc.reg, self, var_index_to_stack_offset);
} }
fn emit_func_call(&mut self, func: Function, args: Vec<Variable>, ret: Option<Variable>, var_index_to_stack_offset: &BTreeMap<usize, usize>) { fn emit_func_call(&mut self, func: Function, args: Vec<Variable>, ret: Option<Variable>, var_index_to_stack_offset: &BTreeMap<usize, usize>) {
@@ -328,7 +334,7 @@ impl Generator {
} }
let mut arg_reg_allocs = Vec::new(); let mut arg_reg_allocs = Vec::new();
for (i, arg) in args.into_iter().enumerate() { for (i, arg) in args.into_iter().enumerate() {
let arg_alloc = load_variable(arg, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); let arg_alloc = load_variable(arg, self, var_index_to_stack_offset);
if i < ARG_REGS.len() { if i < ARG_REGS.len() {
arg_reg_allocs.push(self.register_allocator.alloc_reg(ARG_REGS[i]).expect("Ran out of registers")); arg_reg_allocs.push(self.register_allocator.alloc_reg(ARG_REGS[i]).expect("Ran out of registers"));
self.instrs.push(MoveInstr::new_uncond(ARG_REGS[i], RegisterOrImm::Reg(arg_alloc.reg))); self.instrs.push(MoveInstr::new_uncond(ARG_REGS[i], RegisterOrImm::Reg(arg_alloc.reg)));
@@ -339,7 +345,7 @@ impl Generator {
} }
self.instrs.push(BlInstr::new(func.name.clone())); self.instrs.push(BlInstr::new(func.name.clone()));
if let Some(ret) = ret { if let Some(ret) = ret {
save_variable(ret, REG_R0, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); save_variable(ret, REG_R0, self, var_index_to_stack_offset);
} }
if extra_stack_size > 0 { if extra_stack_size > 0 {
@@ -353,24 +359,24 @@ impl Generator {
let dest_register = dest_alloc.reg; let dest_register = dest_alloc.reg;
match src { match src {
MoveRValue::Var(variable) => { MoveRValue::Var(variable) => {
let src_alloc = load_variable(variable, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); let src_alloc = load_variable(variable, self, var_index_to_stack_offset);
self.instrs.push(MoveInstr::new_uncond(dest_register, RegisterOrImm::Reg(src_alloc.reg))); self.instrs.push(MoveInstr::new_uncond(dest_register, RegisterOrImm::Reg(src_alloc.reg)));
}, },
MoveRValue::ConstInt(literal_int) => emit_load_imm32(dest_register, literal_int, &mut self.instrs), MoveRValue::ConstInt(literal_int) => emit_load_imm32(dest_register, literal_int, &mut self.instrs),
}; };
save_variable(dest, dest_alloc.reg, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); save_variable(dest, dest_alloc.reg, self, var_index_to_stack_offset);
} }
fn emit_load(&mut self, dest: Variable, addr: Variable, var_index_to_stack_offset: &BTreeMap<usize, usize>) { fn emit_load(&mut self, dest: Variable, addr: Variable, var_index_to_stack_offset: &BTreeMap<usize, usize>) {
let addr_alloc = load_variable(addr, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); let addr_alloc = load_variable(addr, self, var_index_to_stack_offset);
let dest_alloc = self.register_allocator.alloc(dest.clone()).expect("Ran out of registers"); let dest_alloc = self.register_allocator.alloc(dest.clone()).expect("Ran out of registers");
self.instrs.push(LoadInstr::new(dest_alloc.reg, addr_alloc.reg, None)); self.instrs.push(LoadInstr::new(dest_alloc.reg, addr_alloc.reg, None));
save_variable(dest, dest_alloc.reg, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); save_variable(dest, dest_alloc.reg, self, var_index_to_stack_offset);
} }
fn emit_store(&mut self, addr: Variable, value: Variable, var_index_to_stack_offset: &BTreeMap<usize, usize>) { fn emit_store(&mut self, addr: Variable, value: Variable, var_index_to_stack_offset: &BTreeMap<usize, usize>) {
let addr_alloc = load_variable(addr, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); let addr_alloc = load_variable(addr, self, var_index_to_stack_offset);
let value_alloc = load_variable(value, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); let value_alloc = load_variable(value, self, var_index_to_stack_offset);
self.instrs.push(StoreInstr::new(value_alloc.reg, addr_alloc.reg, None)); self.instrs.push(StoreInstr::new(value_alloc.reg, addr_alloc.reg, None));
} }
@@ -378,9 +384,9 @@ impl Generator {
let dest_alloc = self.register_allocator.alloc(dest.clone()).expect("Ran out of registers"); let dest_alloc = self.register_allocator.alloc(dest.clone()).expect("Ran out of registers");
let dest_reg = dest_alloc.reg; let dest_reg = dest_alloc.reg;
// should consider left == right // should consider left == right
let left_alloc = load_variable(left.clone(), &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); let left_alloc = load_variable(left.clone(), self, var_index_to_stack_offset);
let (_right_alloc, right_reg) = if left != right { let (_right_alloc, right_reg) = if left != right {
let right_alloc = load_variable(right, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); let right_alloc = load_variable(right, self, var_index_to_stack_offset);
let right_reg = right_alloc.reg; let right_reg = right_alloc.reg;
(Some(right_alloc), right_reg) (Some(right_alloc), right_reg)
} else { } else {
@@ -407,7 +413,7 @@ impl Generator {
self.instrs.push(SubInstr::new(dest_reg, left_alloc.reg, RegisterOrImm::Reg(temp_reg))); self.instrs.push(SubInstr::new(dest_reg, left_alloc.reg, RegisterOrImm::Reg(temp_reg)));
}, },
} }
save_variable(dest, dest_alloc.reg, &mut self.register_allocator, var_index_to_stack_offset, &mut self.instrs); save_variable(dest, dest_alloc.reg, self, var_index_to_stack_offset);
} }
} }