From b29753bc056a4b8ba8b4efb65da71f3169e8aaff Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Fri, 19 Jun 2026 19:17:58 -0500 Subject: [PATCH] Cleaning up parameter/variable distinction; first attempt at managing register spills. WIP. --- dmc-lib/src/ast/function.rs | 2 +- dmc-lib/src/ir/assemble.rs | 94 +++---- dmc-lib/src/ir/ir_block.rs | 39 +-- dmc-lib/src/ir/ir_call.rs | 5 +- dmc-lib/src/ir/ir_expression.rs | 293 +-------------------- dmc-lib/src/ir/ir_function.rs | 6 +- dmc-lib/src/ir/ir_get_field_ref.rs | 19 +- dmc-lib/src/ir/ir_get_field_ref_mut.rs | 20 +- dmc-lib/src/ir/ir_parameter.rs | 2 + dmc-lib/src/ir/ir_parameter_or_variable.rs | 60 ++--- dmc-lib/src/ir/ir_read_field.rs | 2 +- dmc-lib/src/ir/ir_set_field.rs | 31 +-- dmc-lib/src/ir/register_allocation.rs | 62 ++--- dmc-lib/src/ir/variable_locations.rs | 9 +- dmc-lib/src/lowering/mod.rs | 5 +- 15 files changed, 133 insertions(+), 516 deletions(-) diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index 85fc90b..8e5945c 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -435,7 +435,7 @@ impl Function { if class_context.is_some() { let parameter_0 = builder.parameters()[0].clone(); // put it in the self parameter - builder.set_self_parameter_or_variable(IrParameterOrVariable::IrParameter(parameter_0)); + builder.set_self_parameter_or_variable(IrParameterOrVariable::Parameter(parameter_0)); } } diff --git a/dmc-lib/src/ir/assemble.rs b/dmc-lib/src/ir/assemble.rs index 542ea4a..545aa74 100644 --- a/dmc-lib/src/ir/assemble.rs +++ b/dmc-lib/src/ir/assemble.rs @@ -6,6 +6,7 @@ use crate::ir::ir_call::IrCall; use crate::ir::ir_expression::IrExpression; use crate::ir::ir_function::IrFunction; use crate::ir::ir_operation::IrOperation; +use crate::ir::ir_parameter::IrParameter; use crate::ir::ir_return::IrReturn; use crate::ir::ir_statement::IrStatement; use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId}; @@ -17,36 +18,11 @@ use dvm_lib::instruction::{ }; use std::collections::HashMap; -#[deprecated] -pub trait Assemble { - fn assemble(&self, builder: &mut InstructionsBuilder, constants_table: &mut ConstantsTable); -} - -#[deprecated] -pub struct InstructionsBuilder { - instructions: Vec, -} - -impl InstructionsBuilder { - pub fn new() -> Self { - Self { - instructions: vec![], - } - } - - pub fn push(&mut self, instruction: Instruction) { - self.instructions.push(instruction); - } - - pub fn take_instructions(&mut self) -> Vec { - std::mem::take(&mut self.instructions) - } -} - struct FunctionAssemblyContext<'a> { type_infos: &'a Vec, variables_to_type_infos: &'a HashMap, variable_locations: &'a VariableLocations, + parameters: &'a [IrParameter], constants_table: &'a mut ConstantsTable, instructions: Vec, } @@ -63,6 +39,7 @@ pub fn assemble_ir_function( variables_to_type_infos, variable_locations, constants_table, + parameters: ir_function.parameters(), instructions: Vec::new(), }; for block in ir_function.blocks() { @@ -209,9 +186,9 @@ fn assemble_ir_return(ir_return: &IrReturn, ctx: &mut FunctionAssemblyContext) { fn to_move_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> MoveOperand { match ir_expression { - IrExpression::Parameter(ir_parameter) => { - MoveOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } + IrExpression::Parameter(ir_parameter_id) => MoveOperand::Location( + Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()), + ), IrExpression::Variable(ir_variable_id) => MoveOperand::Location(to_location( ctx.variable_locations.get_variable_location(ir_variable_id), )), @@ -229,9 +206,9 @@ fn to_multiply_operand( ctx: &mut FunctionAssemblyContext, ) -> MultiplyOperand { match ir_expression { - IrExpression::Parameter(ir_parameter) => { - MultiplyOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } + IrExpression::Parameter(ir_parameter_id) => MultiplyOperand::Location( + Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()), + ), IrExpression::Variable(ir_variable_id) => { let ir_type_info_id = ctx.variables_to_type_infos[ir_variable_id]; let ir_type_info = &ctx.type_infos[ir_type_info_id]; @@ -254,11 +231,14 @@ fn to_multiply_operand( fn to_add_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> AddOperand { match ir_expression { - IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() { - IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => { - AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) + IrExpression::Parameter(ir_parameter_id) => { + let ir_parameter = &ctx.parameters[*ir_parameter_id]; + match ir_parameter.type_info() { + IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => { + AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) + } } - }, + } IrExpression::Variable(ir_variable_id) => { let ir_type_info_id = ctx.variables_to_type_infos[ir_variable_id]; let ir_type_info = &ctx.type_infos[ir_type_info_id]; @@ -282,15 +262,18 @@ fn to_subtract_operand( ctx: &mut FunctionAssemblyContext, ) -> SubtractOperand { match ir_expression { - IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() { - IrTypeInfo::Int | IrTypeInfo::Double => { - SubtractOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) + IrExpression::Parameter(ir_parameter_id) => { + let ir_parameter = &ctx.parameters[*ir_parameter_id]; + match ir_parameter.type_info() { + IrTypeInfo::Int | IrTypeInfo::Double => SubtractOperand::Location( + Location::StackFrameOffset(ir_parameter.stack_offset()), + ), + _ => panic!( + "Attempt to subtract with non-integer type (found {})", + ir_parameter.type_info() + ), } - _ => panic!( - "Attempt to subtract with non-integer type (found {})", - ir_parameter.type_info() - ), - }, + } IrExpression::Variable(ir_variable) => { let ir_type_info_id = ctx.variables_to_type_infos[ir_variable]; let ir_type_info = &ctx.type_infos[ir_type_info_id]; @@ -317,8 +300,9 @@ fn to_location_or_number( ctx: &mut FunctionAssemblyContext, ) -> LocationOrNumber { match ir_expression { - IrExpression::Parameter(ir_parameter) => { - LocationOrNumber::Location(ir_parameter.as_location()) + IrExpression::Parameter(ir_parameter_id) => { + let ir_parameter = &ctx.parameters[*ir_parameter_id]; + LocationOrNumber::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) } IrExpression::Variable(ir_variable_id) => LocationOrNumber::Location(to_location( ctx.variable_locations.get_variable_location(ir_variable_id), @@ -334,9 +318,9 @@ fn to_location_or_number( fn to_push_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> PushOperand { match ir_expression { - IrExpression::Parameter(ir_parameter) => { - PushOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } + IrExpression::Parameter(ir_parameter_id) => PushOperand::Location( + Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()), + ), IrExpression::Variable(ir_variable_id) => PushOperand::Location(to_location( ctx.variable_locations.get_variable_location(ir_variable_id), )), @@ -354,9 +338,9 @@ fn to_return_operand( ctx: &mut FunctionAssemblyContext, ) -> ReturnOperand { match ir_expression { - IrExpression::Parameter(ir_parameter) => { - ReturnOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } + IrExpression::Parameter(ir_parameter_id) => ReturnOperand::Location( + Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()), + ), IrExpression::Variable(ir_variable) => ReturnOperand::Location(to_location( ctx.variable_locations.get_variable_location(ir_variable), )), @@ -374,9 +358,9 @@ fn to_location_or_integer( ctx: &mut FunctionAssemblyContext, ) -> LocationOrInteger { match ir_expression { - IrExpression::Parameter(ir_parameter) => { - LocationOrInteger::Location(ir_parameter.as_location()) - } + IrExpression::Parameter(ir_parameter_id) => LocationOrInteger::Location( + Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()), + ), IrExpression::Variable(ir_variable_id) => LocationOrInteger::Location(to_location( ctx.variable_locations.get_variable_location(ir_variable_id), )), diff --git a/dmc-lib/src/ir/ir_block.rs b/dmc-lib/src/ir/ir_block.rs index cedda68..8d81539 100644 --- a/dmc-lib/src/ir/ir_block.rs +++ b/dmc-lib/src/ir/ir_block.rs @@ -1,8 +1,7 @@ use crate::ir::ir_statement::IrStatement; use crate::ir::ir_variable::IrVariableId; -use crate::ir::register_allocation::{HasVrUsers, RegisterAssignment, VrUser}; -use crate::offset_counter::OffsetCounter; -use std::collections::{HashMap, HashSet}; +use crate::ir::register_allocation::VrUser; +use std::collections::HashSet; pub type IrBlockId = usize; @@ -34,19 +33,6 @@ impl IrBlock { } } -impl HasVrUsers for IrBlock { - fn vr_users(&self) -> Vec<&dyn VrUser> { - self.statements.iter().map(|s| s as &dyn VrUser).collect() - } - - fn vr_users_mut(&mut self) -> Vec<&mut dyn VrUser> { - self.statements - .iter_mut() - .map(|s| s as &mut dyn VrUser) - .collect() - } -} - impl VrUser for IrBlock { fn vr_definitions(&self) -> HashSet { self.statements @@ -58,27 +44,6 @@ impl VrUser for IrBlock { fn vr_uses(&self) -> HashSet { self.statements.iter().flat_map(|s| s.vr_uses()).collect() } - - fn propagate_spills(&mut self, spills: &HashSet) { - for statement in &mut self.statements { - statement.propagate_spills(spills); - } - } - - fn propagate_register_assignments( - &mut self, - assignments: &HashMap, - ) { - for statement in &mut self.statements { - statement.propagate_register_assignments(assignments); - } - } - - fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) { - for statement in &mut self.statements { - statement.propagate_stack_offsets(counter); - } - } } // diff --git a/dmc-lib/src/ir/ir_call.rs b/dmc-lib/src/ir/ir_call.rs index 7d6402d..6b3f7c3 100644 --- a/dmc-lib/src/ir/ir_call.rs +++ b/dmc-lib/src/ir/ir_call.rs @@ -39,7 +39,10 @@ impl IrCall { impl VrUser for IrCall { fn vr_uses(&self) -> HashSet { - self.arguments.iter().flat_map(|a| a.vr_uses()).collect() + self.arguments + .iter() + .flat_map(|ir_expression| ir_expression.vr_uses()) + .collect() } } diff --git a/dmc-lib/src/ir/ir_expression.rs b/dmc-lib/src/ir/ir_expression.rs index 49b8165..b0b22e1 100644 --- a/dmc-lib/src/ir/ir_expression.rs +++ b/dmc-lib/src/ir/ir_expression.rs @@ -1,305 +1,18 @@ -use crate::constants_table::ConstantsTable; -use crate::ir::ir_parameter::IrParameter; -use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId}; +use crate::ir::ir_parameter::IrParameterId; use crate::ir::ir_variable::IrVariableId; use crate::ir::register_allocation::VrUser; -use crate::ir::variable_locations::{VariableLocation, VariableLocations}; -use dvm_lib::instruction::{ - AddOperand, Location, LocationOrInteger, LocationOrNumber, MoveOperand, MultiplyOperand, - PushOperand, ReturnOperand, SetFieldOperand, SubtractOperand, -}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::fmt::{Display, Formatter}; use std::rc::Rc; pub enum IrExpression { - Parameter(Rc), + Parameter(IrParameterId), Variable(IrVariableId), Int(i32), Double(f64), String(Rc), } -impl IrExpression { - pub fn move_operand( - &self, - variable_locations: &VariableLocations, - constants_table: &mut ConstantsTable, - ) -> MoveOperand { - match self { - IrExpression::Parameter(ir_parameter) => { - MoveOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } - IrExpression::Variable(ir_variable_id) => { - match variable_locations.get_variable_location(ir_variable_id) { - VariableLocation::Register(register_assignment) => { - MoveOperand::Location(Location::Register(register_assignment)) - } - VariableLocation::Stack(stack_frame_offset) => { - MoveOperand::Location(Location::StackFrameOffset(stack_frame_offset)) - } - } - } - IrExpression::Int(i) => MoveOperand::Int(*i), - IrExpression::Double(d) => MoveOperand::Double(*d), - IrExpression::String(s) => { - let constant_name = constants_table.get_or_insert(s); - MoveOperand::String(constant_name) - } - } - } - - pub fn push_operand( - &self, - variable_locations: &VariableLocations, - constants_table: &mut ConstantsTable, - ) -> PushOperand { - match self { - IrExpression::Parameter(ir_parameter) => { - PushOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } - IrExpression::Variable(ir_variable_id) => { - match variable_locations.get_variable_location(ir_variable_id) { - VariableLocation::Register(register_assignment) => { - PushOperand::Location(Location::Register(register_assignment)) - } - VariableLocation::Stack(stack_frame_offset) => { - PushOperand::Location(Location::StackFrameOffset(stack_frame_offset)) - } - } - } - IrExpression::Int(i) => PushOperand::Int(*i), - IrExpression::Double(d) => PushOperand::Double(*d), - IrExpression::String(s) => { - let constant_name = constants_table.get_or_insert(s); - PushOperand::String(constant_name) - } - } - } - - pub fn add_operand( - &self, - type_infos: &Vec, - variables_to_type_infos: &HashMap, - variable_locations: &VariableLocations, - constants_table: &mut ConstantsTable, - ) -> AddOperand { - match self { - IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() { - IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => { - AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } - }, - IrExpression::Variable(ir_variable_id) => { - let ir_type_info_id = variables_to_type_infos[ir_variable_id]; - let ir_type_info = &type_infos[ir_type_info_id]; - match ir_type_info { - IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => { - match variable_locations.get_variable_location(ir_variable_id) { - VariableLocation::Register(register_assignment) => { - AddOperand::Location(Location::Register(register_assignment)) - } - VariableLocation::Stack(stack_frame_offset) => { - AddOperand::Location(Location::StackFrameOffset(stack_frame_offset)) - } - } - } - } - } - IrExpression::Int(i) => AddOperand::Int(*i), - IrExpression::Double(d) => AddOperand::Double(*d), - IrExpression::String(s) => { - let constant_name = constants_table.get_or_insert(s); - AddOperand::String(constant_name) - } - } - } - - pub fn subtract_operand( - &self, - type_infos: &Vec, - variables_to_type_infos: &HashMap, - variable_locations: &VariableLocations, - ) -> SubtractOperand { - match self { - IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() { - IrTypeInfo::Int | IrTypeInfo::Double => SubtractOperand::Location( - Location::StackFrameOffset(ir_parameter.stack_offset()), - ), - _ => panic!( - "Attempt to subtract with non-integer type (found {})", - ir_parameter.type_info() - ), - }, - IrExpression::Variable(ir_variable) => { - let ir_type_info_id = variables_to_type_infos[ir_variable]; - let ir_type_info = &type_infos[ir_type_info_id]; - match ir_type_info { - IrTypeInfo::Int | IrTypeInfo::Double => match variable_locations - .get_variable_location(ir_variable) - { - VariableLocation::Register(register_assignment) => { - SubtractOperand::Location(Location::Register(register_assignment)) - } - VariableLocation::Stack(stack_frame_offset) => SubtractOperand::Location( - Location::StackFrameOffset(stack_frame_offset), - ), - }, - _ => panic!( - "Attempt to subtract with non-number type (found {})", - ir_type_info - ), - } - } - IrExpression::Int(i) => SubtractOperand::Int(*i), - IrExpression::Double(d) => SubtractOperand::Double(*d), - IrExpression::String(_) => { - panic!("Attempt to subtract with a string"); - } - } - } - - pub fn multiply_operand( - &self, - type_infos: &Vec, - variables_to_type_infos: &HashMap, - variables_locations: &VariableLocations, - ) -> MultiplyOperand { - match self { - IrExpression::Parameter(ir_parameter) => { - MultiplyOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } - IrExpression::Variable(ir_variable_id) => { - let ir_type_info_id = variables_to_type_infos[ir_variable_id]; - let ir_type_info = &type_infos[ir_type_info_id]; - match ir_type_info { - IrTypeInfo::Int | IrTypeInfo::Double => { - match variables_locations.get_variable_location(ir_variable_id) { - VariableLocation::Register(register_assignment) => { - MultiplyOperand::Location(Location::Register(register_assignment)) - } - VariableLocation::Stack(stack_frame_offset) => { - MultiplyOperand::Location(Location::StackFrameOffset( - stack_frame_offset, - )) - } - } - } - _ => panic!("Attempt to multiply non-number (found {})", ir_type_info), - } - } - IrExpression::Int(i) => MultiplyOperand::Int(*i), - IrExpression::Double(d) => MultiplyOperand::Double(*d), - IrExpression::String(_) => { - panic!("Attempt to multiply with a string"); - } - } - } - - pub fn return_operand( - &self, - variable_locations: &VariableLocations, - constants_table: &mut ConstantsTable, - ) -> ReturnOperand { - match self { - IrExpression::Parameter(ir_parameter) => { - ReturnOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } - IrExpression::Variable(ir_variable) => { - match variable_locations.get_variable_location(ir_variable) { - VariableLocation::Register(register_assignment) => { - ReturnOperand::Location(Location::Register(register_assignment)) - } - VariableLocation::Stack(stack_frame_offset) => { - ReturnOperand::Location(Location::StackFrameOffset(stack_frame_offset)) - } - } - } - IrExpression::Int(i) => ReturnOperand::Int(*i), - IrExpression::Double(d) => ReturnOperand::Double(*d), - IrExpression::String(s) => { - let constant_name = constants_table.get_or_insert(s); - ReturnOperand::String(constant_name) - } - } - } - - pub fn set_field_operand( - &self, - variable_locations: &VariableLocations, - constants_table: &mut ConstantsTable, - ) -> SetFieldOperand { - match self { - IrExpression::Parameter(ir_parameter) => { - SetFieldOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset())) - } - IrExpression::Variable(ir_variable_id) => { - match variable_locations.get_variable_location(ir_variable_id) { - VariableLocation::Register(register_assignment) => { - SetFieldOperand::Location(Location::Register(register_assignment)) - } - VariableLocation::Stack(stack_frame_offset) => { - SetFieldOperand::Location(Location::StackFrameOffset(stack_frame_offset)) - } - } - } - IrExpression::Int(i) => SetFieldOperand::Int(*i), - IrExpression::Double(d) => SetFieldOperand::Double(*d), - IrExpression::String(s) => { - let constant_name = constants_table.get_or_insert(s); - SetFieldOperand::String(constant_name) - } - } - } - - pub fn as_location_or_number( - &self, - variable_locations: &VariableLocations, - ) -> LocationOrNumber { - match self { - IrExpression::Parameter(ir_parameter) => { - LocationOrNumber::Location(ir_parameter.as_location()) - } - IrExpression::Variable(ir_variable_id) => LocationOrNumber::Location( - match variable_locations.get_variable_location(ir_variable_id) { - VariableLocation::Register(register_assignment) => { - Location::Register(register_assignment) - } - VariableLocation::Stack(stack_frame_offset) => { - Location::StackFrameOffset(stack_frame_offset) - } - }, - ), - IrExpression::Int(i) => LocationOrNumber::Int(*i), - IrExpression::Double(d) => LocationOrNumber::Double(*d), - _ => panic!("Attempt to convert {} to a location or number", self), - } - } - - pub fn as_location_or_integer( - &self, - variable_locations: &VariableLocations, - ) -> LocationOrInteger { - match self { - IrExpression::Parameter(ir_parameter) => { - LocationOrInteger::Location(ir_parameter.as_location()) - } - IrExpression::Variable(ir_variable_id) => LocationOrInteger::Location( - match variable_locations.get_variable_location(ir_variable_id) { - VariableLocation::Register(register_assignment) => { - Location::Register(register_assignment) - } - VariableLocation::Stack(stack_frame_offset) => { - Location::StackFrameOffset(stack_frame_offset) - } - }, - ), - IrExpression::Int(i) => LocationOrInteger::Int(*i), - _ => panic!("Attempt to convert {} to a location or integer", self), - } - } -} - impl Display for IrExpression { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { diff --git a/dmc-lib/src/ir/ir_function.rs b/dmc-lib/src/ir/ir_function.rs index 2a92af0..048d818 100644 --- a/dmc-lib/src/ir/ir_function.rs +++ b/dmc-lib/src/ir/ir_function.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub struct IrFunction { fqn: Rc, - parameters: Vec>, + parameters: Vec, variables: Vec, return_type_info: Option, blocks: Vec, @@ -21,7 +21,7 @@ pub struct IrFunction { impl IrFunction { pub fn new( fqn: Rc, - parameters: Vec>, + parameters: Vec, variables: Vec, return_type_info: Option, blocks: Vec, @@ -43,7 +43,7 @@ impl IrFunction { &self.blocks } - pub fn parameters(&self) -> &[Rc] { + pub fn parameters(&self) -> &[IrParameter] { &self.parameters } diff --git a/dmc-lib/src/ir/ir_get_field_ref.rs b/dmc-lib/src/ir/ir_get_field_ref.rs index 7e220b6..7d84926 100644 --- a/dmc-lib/src/ir/ir_get_field_ref.rs +++ b/dmc-lib/src/ir/ir_get_field_ref.rs @@ -1,23 +1,24 @@ +use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; use crate::ir::ir_variable::IrVariableId; use crate::ir::register_allocation::VrUser; use std::collections::HashSet; use std::fmt::{Display, Formatter}; pub struct IrGetFieldRef { - self_variable_id: IrVariableId, + self_variable_or_parameter: IrParameterOrVariable, field_index: usize, } impl IrGetFieldRef { - pub fn new(self_variable_id: IrVariableId, field_index: usize) -> Self { + pub fn new(self_variable_or_parameter: IrParameterOrVariable, field_index: usize) -> Self { Self { - self_variable_id, + self_variable_or_parameter, field_index, } } - pub fn self_variable_id(self) -> IrVariableId { - self.self_variable_id + pub fn self_variable_id(&self) -> &IrParameterOrVariable { + &self.self_variable_or_parameter } pub fn field_index(&self) -> usize { @@ -27,12 +28,16 @@ impl IrGetFieldRef { impl Display for IrGetFieldRef { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "&{}.{}", self.self_variable_id, self.field_index) + write!( + f, + "&{}.{}", + self.self_variable_or_parameter, self.field_index + ) } } impl VrUser for IrGetFieldRef { fn vr_uses(&self) -> HashSet { - todo!() + self.self_variable_or_parameter.vr_uses() } } diff --git a/dmc-lib/src/ir/ir_get_field_ref_mut.rs b/dmc-lib/src/ir/ir_get_field_ref_mut.rs index 37f4946..da47e4f 100644 --- a/dmc-lib/src/ir/ir_get_field_ref_mut.rs +++ b/dmc-lib/src/ir/ir_get_field_ref_mut.rs @@ -1,23 +1,24 @@ +use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; use crate::ir::ir_variable::IrVariableId; use crate::ir::register_allocation::VrUser; use std::collections::HashSet; use std::fmt::{Display, Formatter}; pub struct IrGetFieldRefMut { - self_ir_variable: IrVariableId, + self_variable_or_parameter: IrParameterOrVariable, field_index: usize, } impl IrGetFieldRefMut { - pub fn new(self_ir_variable: IrVariableId, field_index: usize) -> Self { + pub fn new(self_variable_or_parameter: IrParameterOrVariable, field_index: usize) -> Self { Self { - self_ir_variable, + self_variable_or_parameter, field_index, } } - pub fn self_ir_variable(&self) -> IrVariableId { - self.self_ir_variable + pub fn self_ir_variable(&self) -> &IrParameterOrVariable { + &self.self_variable_or_parameter } pub fn field_index(&self) -> usize { @@ -27,12 +28,17 @@ impl IrGetFieldRefMut { impl Display for IrGetFieldRefMut { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "&mut {}.{}", self.self_ir_variable, self.field_index()) + write!( + f, + "&mut {}.{}", + self.self_variable_or_parameter, + self.field_index() + ) } } impl VrUser for IrGetFieldRefMut { fn vr_uses(&self) -> HashSet { - todo!() + self.self_variable_or_parameter.vr_uses() } } diff --git a/dmc-lib/src/ir/ir_parameter.rs b/dmc-lib/src/ir/ir_parameter.rs index 0f3f257..c26d1ce 100644 --- a/dmc-lib/src/ir/ir_parameter.rs +++ b/dmc-lib/src/ir/ir_parameter.rs @@ -3,6 +3,8 @@ use dvm_lib::instruction::Location; use std::fmt::{Display, Formatter}; use std::rc::Rc; +pub type IrParameterId = usize; + pub struct IrParameter { name: Rc, type_info: IrTypeInfo, diff --git a/dmc-lib/src/ir/ir_parameter_or_variable.rs b/dmc-lib/src/ir/ir_parameter_or_variable.rs index 79a82c8..4de0110 100644 --- a/dmc-lib/src/ir/ir_parameter_or_variable.rs +++ b/dmc-lib/src/ir/ir_parameter_or_variable.rs @@ -1,51 +1,27 @@ -use crate::ir::ir_parameter::IrParameter; -use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVirtualRegisterVariable}; -use dvm_lib::instruction::Location; -use std::cell::RefCell; +use crate::ir::ir_parameter::IrParameterId; +use crate::ir::ir_variable::IrVariableId; +use crate::ir::register_allocation::VrUser; use std::collections::HashSet; -use std::fmt::{Display, Formatter}; -use std::rc::Rc; +use std::fmt::Display; -#[derive(Clone)] -#[deprecated] +#[derive(Clone, Debug)] pub enum IrParameterOrVariable { - IrParameter(Rc), - Variable(Rc>), -} - -impl IrParameterOrVariable { - pub fn as_location(&self) -> Location { - match self { - IrParameterOrVariable::IrParameter(ir_parameter) => { - Location::StackFrameOffset(ir_parameter.stack_offset()) - } - IrParameterOrVariable::Variable(ir_variable) => { - ir_variable.borrow().descriptor().as_location() - } - } - } - - pub fn vr_uses(&self) -> HashSet { - if let IrParameterOrVariable::Variable(ir_variable) = &self { - if let IrVariableDescriptor::VirtualRegister(vr_variable) = - ir_variable.borrow().descriptor() - { - return HashSet::from([vr_variable.clone()]); - } - } - HashSet::new() - } + Parameter(IrParameterId), + Variable(IrVariableId), } impl Display for IrParameterOrVariable { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - IrParameterOrVariable::IrParameter(ir_parameter) => { - write!(f, "{}", ir_parameter) - } - IrParameterOrVariable::Variable(ir_variable) => { - write!(f, "{}", ir_variable.borrow()) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self) + } +} + +impl VrUser for IrParameterOrVariable { + fn vr_uses(&self) -> HashSet { + if let IrParameterOrVariable::Variable(ir_variable_id) = self { + HashSet::from([*ir_variable_id]) + } else { + HashSet::new() } } } diff --git a/dmc-lib/src/ir/ir_read_field.rs b/dmc-lib/src/ir/ir_read_field.rs index 532fef4..7390b9a 100644 --- a/dmc-lib/src/ir/ir_read_field.rs +++ b/dmc-lib/src/ir/ir_read_field.rs @@ -19,7 +19,7 @@ impl IrReadField { impl VrUser for IrReadField { fn vr_uses(&self) -> HashSet { - todo!() + HashSet::from([self.field_ref_variable]) } } diff --git a/dmc-lib/src/ir/ir_set_field.rs b/dmc-lib/src/ir/ir_set_field.rs index 61c1a0d..af3148f 100644 --- a/dmc-lib/src/ir/ir_set_field.rs +++ b/dmc-lib/src/ir/ir_set_field.rs @@ -1,20 +1,18 @@ use crate::ir::ir_expression::IrExpression; -use crate::ir::ir_variable::{IrVariable, IrVariableId}; +use crate::ir::ir_variable::IrVariableId; use crate::ir::register_allocation::VrUser; -use std::cell::RefCell; use std::collections::HashSet; use std::fmt::{Display, Formatter}; -use std::rc::Rc; pub struct IrSetField { - field_ref_variable: Rc>, + field_ref_variable: IrVariableId, initializer: Box, } impl IrSetField { - pub fn new(field_ref_variable: &Rc>, initializer: IrExpression) -> Self { + pub fn new(field_ref_variable: IrVariableId, initializer: IrExpression) -> Self { Self { - field_ref_variable: field_ref_variable.clone(), + field_ref_variable, initializer: initializer.into(), } } @@ -22,16 +20,10 @@ impl IrSetField { impl VrUser for IrSetField { fn vr_uses(&self) -> HashSet { - // let mut set = HashSet::new(); - // match self.field_ref_variable.borrow().descriptor() { - // IrVariableDescriptor::VirtualRegister(vr_variable) => { - // set.insert(vr_variable.clone()); - // } - // IrVariableDescriptor::Stack(_) => {} - // } - // set.extend(self.initializer.vr_uses()); - // set - todo!() + let mut set = HashSet::new(); + set.insert(self.field_ref_variable); + set.extend(self.initializer.vr_uses()); + set } } @@ -45,11 +37,6 @@ impl VrUser for IrSetField { impl Display for IrSetField { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!( - f, - "*{} = {}", - self.field_ref_variable.borrow(), - self.initializer - ) + write!(f, "*{} = {}", self.field_ref_variable, self.initializer) } } diff --git a/dmc-lib/src/ir/register_allocation.rs b/dmc-lib/src/ir/register_allocation.rs index 6940cf1..627de51 100644 --- a/dmc-lib/src/ir/register_allocation.rs +++ b/dmc-lib/src/ir/register_allocation.rs @@ -1,7 +1,6 @@ use crate::ir::ir_block::IrBlock; use crate::ir::ir_variable::IrVariableId; use crate::ir::variable_locations::VariableLocations; -use crate::offset_counter::OffsetCounter; use dvm_lib::instruction::{Register, StackFrameOffset}; use std::collections::{HashMap, HashSet}; @@ -31,17 +30,9 @@ pub fn block_live_in_live_out(ir_block: &IrBlock) -> (LivenessSets, LivenessSets } // in: use(s) U ( out(s) - def(s) ) - let use_s = ir_statement - .vr_uses() - .iter() - .map(|u| *u) - .collect::>(); + let use_s = ir_statement.vr_uses(); let out_s = &live_out[statement_index]; - let def_s = ir_statement - .vr_definitions() - .iter() - .map(|d| *d) - .collect::>(); + let def_s = ir_statement.vr_definitions(); let rhs = out_s - &def_s; let new_ins = use_s.union(&rhs).map(|v| *v).collect::>(); @@ -66,11 +57,16 @@ pub fn block_interference_graph( ir_block: &IrBlock, spilled: &HashSet, ) -> InterferenceGraph { - // create a set of all variables used in the block + // create a set of all variables used in the block that are not already spilled let mut all_vr_variables: HashSet = HashSet::new(); for statement in ir_block.statements() { - all_vr_variables.extend(statement.vr_definitions()); - all_vr_variables.extend(statement.vr_uses()); + let definitions = statement.vr_definitions(); + let uses = statement.vr_uses(); + let not_already_spilled = definitions + .union(&uses) + .filter(|v| !spilled.contains(*v)) + .collect::>(); + all_vr_variables.extend(not_already_spilled); } // create graph and init all variables' outgoing-edge sets @@ -84,6 +80,11 @@ pub fn block_interference_graph( for (statement_index, ir_statement) in ir_block.statements().iter().enumerate() { let statement_live_out = &live_out[statement_index]; for definition_vr_variable in ir_statement.vr_definitions() { + // check for spill + if spilled.contains(&definition_vr_variable) { + continue; + } + for live_out_variable in statement_live_out { // we do the following check to avoid adding an edge to itself if definition_vr_variable != *live_out_variable { @@ -106,9 +107,10 @@ pub fn block_assign_registers(ir_block: &IrBlock, register_count: usize) -> Vari let mut interference_graph = block_interference_graph(ir_block, &spilled); let (registers, new_spills) = registers_and_spills(&mut interference_graph, register_count); - if spilled != new_spills { - spilled = new_spills; // todo: figure out if this works algorithmically - } else { + let old_n_spilled = spilled.len(); + spilled.extend(new_spills); + // check if added zero spills to get to fixed point + if old_n_spilled == spilled.len() { let mut spills_to_stack_offsets: HashMap = HashMap::new(); let mut offset_counter = 0isize; @@ -121,36 +123,12 @@ pub fn block_assign_registers(ir_block: &IrBlock, register_count: usize) -> Vari } } -pub trait HasVrUsers { - fn vr_users(&self) -> Vec<&dyn VrUser>; - fn vr_users_mut(&mut self) -> Vec<&mut dyn VrUser>; -} - pub trait VrUser { fn vr_definitions(&self) -> HashSet { HashSet::new() } - #[deprecated] fn vr_uses(&self) -> HashSet; - - #[deprecated] - fn propagate_spills(&mut self, _spills: &HashSet) { - // default no-op - } - - #[deprecated] - fn propagate_register_assignments( - &mut self, - _assignments: &HashMap, - ) { - // default no-op - } - - #[deprecated] - fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) { - // default no-op - } } #[derive(Debug)] @@ -160,7 +138,7 @@ struct WorkItem { color: bool, } -pub fn registers_and_spills( +fn registers_and_spills( interference_graph: &mut InterferenceGraph, k: usize, ) -> ( diff --git a/dmc-lib/src/ir/variable_locations.rs b/dmc-lib/src/ir/variable_locations.rs index 42d69eb..56e107c 100644 --- a/dmc-lib/src/ir/variable_locations.rs +++ b/dmc-lib/src/ir/variable_locations.rs @@ -1,22 +1,23 @@ use crate::ir::ir_variable::IrVariableId; use crate::ir::register_allocation::RegisterAssignment; -use dvm_lib::instruction::StackFrameOffset; use std::collections::HashMap; +pub type StackVariableOffset = isize; + pub enum VariableLocation { Register(RegisterAssignment), - Stack(StackFrameOffset), + Stack(StackVariableOffset), } pub struct VariableLocations { register_variables: HashMap, - stack_variables: HashMap, + stack_variables: HashMap, } impl VariableLocations { pub fn new( register_variables: HashMap, - stack_variables: HashMap, + stack_variables: HashMap, ) -> Self { Self { register_variables, diff --git a/dmc-lib/src/lowering/mod.rs b/dmc-lib/src/lowering/mod.rs index a9da20b..0e877f8 100644 --- a/dmc-lib/src/lowering/mod.rs +++ b/dmc-lib/src/lowering/mod.rs @@ -161,10 +161,7 @@ fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) { let ir_function = IrFunction::new( function_symbol.fqn_owned(), - lower_to_ir_parameters(function, ctx) - .into_iter() - .map(|ir_parameter| Rc::new(ir_parameter)) - .collect(), + lower_to_ir_parameters(function, ctx), fn_ctx.ir_variables, return_type_info_to_ir_type_info(return_type_info), fn_ctx.blocks,