Cleaning up parameter/variable distinction; first attempt at managing register spills. WIP.

This commit is contained in:
Jesse Brault 2026-06-19 19:17:58 -05:00
parent 737d7b4232
commit b29753bc05
15 changed files with 133 additions and 516 deletions

View File

@ -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));
}
}

View File

@ -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<Instruction>,
}
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<Instruction> {
std::mem::take(&mut self.instructions)
}
}
struct FunctionAssemblyContext<'a> {
type_infos: &'a Vec<IrTypeInfo>,
variables_to_type_infos: &'a HashMap<IrVariableId, IrTypeInfoId>,
variable_locations: &'a VariableLocations,
parameters: &'a [IrParameter],
constants_table: &'a mut ConstantsTable,
instructions: Vec<Instruction>,
}
@ -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() {
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()
),
},
}
}
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),
)),

View File

@ -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<IrVariableId> {
self.statements
@ -58,27 +44,6 @@ impl VrUser for IrBlock {
fn vr_uses(&self) -> HashSet<IrVariableId> {
self.statements.iter().flat_map(|s| s.vr_uses()).collect()
}
fn propagate_spills(&mut self, spills: &HashSet<IrVariableId>) {
for statement in &mut self.statements {
statement.propagate_spills(spills);
}
}
fn propagate_register_assignments(
&mut self,
assignments: &HashMap<IrVariableId, RegisterAssignment>,
) {
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);
}
}
}
//

View File

@ -39,7 +39,10 @@ impl IrCall {
impl VrUser for IrCall {
fn vr_uses(&self) -> HashSet<IrVariableId> {
self.arguments.iter().flat_map(|a| a.vr_uses()).collect()
self.arguments
.iter()
.flat_map(|ir_expression| ir_expression.vr_uses())
.collect()
}
}

View File

@ -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<IrParameter>),
Parameter(IrParameterId),
Variable(IrVariableId),
Int(i32),
Double(f64),
String(Rc<str>),
}
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<IrTypeInfo>,
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
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<IrTypeInfo>,
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
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<IrTypeInfo>,
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
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 {

View File

@ -12,7 +12,7 @@ use std::rc::Rc;
pub struct IrFunction {
fqn: Rc<str>,
parameters: Vec<Rc<IrParameter>>,
parameters: Vec<IrParameter>,
variables: Vec<IrVariable>,
return_type_info: Option<IrTypeInfo>,
blocks: Vec<IrBlock>,
@ -21,7 +21,7 @@ pub struct IrFunction {
impl IrFunction {
pub fn new(
fqn: Rc<str>,
parameters: Vec<Rc<IrParameter>>,
parameters: Vec<IrParameter>,
variables: Vec<IrVariable>,
return_type_info: Option<IrTypeInfo>,
blocks: Vec<IrBlock>,
@ -43,7 +43,7 @@ impl IrFunction {
&self.blocks
}
pub fn parameters(&self) -> &[Rc<IrParameter>] {
pub fn parameters(&self) -> &[IrParameter] {
&self.parameters
}

View File

@ -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<IrVariableId> {
todo!()
self.self_variable_or_parameter.vr_uses()
}
}

View File

@ -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<IrVariableId> {
todo!()
self.self_variable_or_parameter.vr_uses()
}
}

View File

@ -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<str>,
type_info: IrTypeInfo,

View File

@ -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<IrParameter>),
Variable(Rc<RefCell<IrVariable>>),
}
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<IrVirtualRegisterVariable> {
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<IrVariableId> {
if let IrParameterOrVariable::Variable(ir_variable_id) = self {
HashSet::from([*ir_variable_id])
} else {
HashSet::new()
}
}
}

View File

@ -19,7 +19,7 @@ impl IrReadField {
impl VrUser for IrReadField {
fn vr_uses(&self) -> HashSet<IrVariableId> {
todo!()
HashSet::from([self.field_ref_variable])
}
}

View File

@ -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<RefCell<IrVariable>>,
field_ref_variable: IrVariableId,
initializer: Box<IrExpression>,
}
impl IrSetField {
pub fn new(field_ref_variable: &Rc<RefCell<IrVariable>>, 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<IrVariableId> {
// 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)
}
}

View File

@ -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::<HashSet<_>>();
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::<HashSet<_>>();
let def_s = ir_statement.vr_definitions();
let rhs = out_s - &def_s;
let new_ins = use_s.union(&rhs).map(|v| *v).collect::<HashSet<_>>();
@ -66,11 +57,16 @@ pub fn block_interference_graph(
ir_block: &IrBlock,
spilled: &HashSet<IrVariableId>,
) -> 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<IrVariableId> = 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::<HashSet<_>>();
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<IrVariableId, StackFrameOffset> =
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<IrVariableId> {
HashSet::new()
}
#[deprecated]
fn vr_uses(&self) -> HashSet<IrVariableId>;
#[deprecated]
fn propagate_spills(&mut self, _spills: &HashSet<IrVariableId>) {
// default no-op
}
#[deprecated]
fn propagate_register_assignments(
&mut self,
_assignments: &HashMap<IrVariableId, RegisterAssignment>,
) {
// 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,
) -> (

View File

@ -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<IrVariableId, RegisterAssignment>,
stack_variables: HashMap<IrVariableId, StackFrameOffset>,
stack_variables: HashMap<IrVariableId, StackVariableOffset>,
}
impl VariableLocations {
pub fn new(
register_variables: HashMap<IrVariableId, RegisterAssignment>,
stack_variables: HashMap<IrVariableId, StackFrameOffset>,
stack_variables: HashMap<IrVariableId, StackVariableOffset>,
) -> Self {
Self {
register_variables,

View File

@ -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,