Refactor to use IrBinaryOperation.

This commit is contained in:
Jesse Brault 2026-03-15 12:55:00 -05:00
parent 863c3fef5d
commit f9373a687f
9 changed files with 140 additions and 305 deletions

View File

@ -2,12 +2,11 @@ use crate::ast::expression::Expression;
use crate::ast::ir_builder::IrBuilder; use crate::ast::ir_builder::IrBuilder;
use crate::diagnostic::Diagnostic; use crate::diagnostic::Diagnostic;
use crate::error_codes::BINARY_INCOMPATIBLE_TYPES; use crate::error_codes::BINARY_INCOMPATIBLE_TYPES;
use crate::ir::ir_add::IrAdd;
use crate::ir::ir_assign::IrAssign; use crate::ir::ir_assign::IrAssign;
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
use crate::ir::ir_expression::IrExpression; use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_operation::IrOperation; use crate::ir::ir_operation::IrOperation;
use crate::ir::ir_statement::IrStatement; use crate::ir::ir_statement::IrStatement;
use crate::ir::ir_subtract::IrSubtract;
use crate::ir::ir_variable::IrVariable; use crate::ir::ir_variable::IrVariable;
use crate::source_range::SourceRange; use crate::source_range::SourceRange;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
@ -179,16 +178,17 @@ impl BinaryExpression {
.rhs .rhs
.to_ir_expression(builder, symbol_table) .to_ir_expression(builder, symbol_table)
.expect("Attempt to use a non-value expression in binary expression."); .expect("Attempt to use a non-value expression in binary expression.");
match self.op { let ir_binary_operation = match self.op {
BinaryOperation::Multiply => { BinaryOperation::Multiply => {
todo!() IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Multiply)
} }
BinaryOperation::Divide => { BinaryOperation::Divide => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Divide),
todo!() BinaryOperation::Add => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Add),
BinaryOperation::Subtract => {
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Subtract)
} }
BinaryOperation::Add => IrOperation::Add(IrAdd::new(lhs, rhs)), };
BinaryOperation::Subtract => IrOperation::Subtract(IrSubtract::new(lhs, rhs)), IrOperation::Binary(ir_binary_operation)
}
} }
pub fn to_ir_expression( pub fn to_ir_expression(

View File

@ -2,8 +2,8 @@ use crate::ast::expression::Expression;
use crate::ast::ir_builder::IrBuilder; use crate::ast::ir_builder::IrBuilder;
use crate::diagnostic::Diagnostic; use crate::diagnostic::Diagnostic;
use crate::ir::ir_assign::IrAssign; use crate::ir::ir_assign::IrAssign;
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
use crate::ir::ir_expression::IrExpression; use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_multiply::IrMultiply;
use crate::ir::ir_operation::IrOperation; use crate::ir::ir_operation::IrOperation;
use crate::ir::ir_statement::IrStatement; use crate::ir::ir_statement::IrStatement;
use crate::ir::ir_variable::IrVariable; use crate::ir::ir_variable::IrVariable;
@ -87,8 +87,11 @@ impl NegativeExpression {
_ => panic!("Trying to multiply with a non-integer/double"), _ => panic!("Trying to multiply with a non-integer/double"),
}; };
let operation = let operation = IrOperation::Binary(IrBinaryOperation::new(
IrOperation::Multiply(IrMultiply::new(IrExpression::Parameter(parameter), rhs)); IrExpression::Parameter(parameter),
rhs,
IrBinaryOperator::Multiply,
));
let assign = IrAssign::new(destination.clone(), operation); let assign = IrAssign::new(destination.clone(), operation);
builder builder
@ -110,8 +113,11 @@ impl NegativeExpression {
_ => panic!("Trying to multiply with a non-integer/double"), _ => panic!("Trying to multiply with a non-integer/double"),
}; };
let operation = let operation = IrOperation::Binary(IrBinaryOperation::new(
IrOperation::Multiply(IrMultiply::new(IrExpression::Variable(variable), rhs)); IrExpression::Variable(variable),
rhs,
IrBinaryOperator::Multiply,
));
let assign = IrAssign::new(destination.clone(), operation); let assign = IrAssign::new(destination.clone(), operation);
builder builder

View File

@ -1,75 +0,0 @@
use crate::constants_table::ConstantsTable;
use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_variable::IrVrVariableDescriptor;
use crate::ir::register_allocation::{OffsetCounter, VrUser};
use dvm_lib::instruction::AddOperand;
use std::collections::{HashMap, HashSet};
use std::fmt::{Display, Formatter};
pub struct IrAdd {
left: Box<IrExpression>,
right: Box<IrExpression>,
}
impl IrAdd {
pub fn new(left: IrExpression, right: IrExpression) -> Self {
Self {
left: left.into(),
right: right.into(),
}
}
pub fn left(&self) -> &IrExpression {
&self.left
}
pub fn right(&self) -> &IrExpression {
&self.right
}
pub fn operand_pair(&self, constants_table: &mut ConstantsTable) -> (AddOperand, AddOperand) {
(
self.left.add_operand(constants_table),
self.right.add_operand(constants_table),
)
}
}
impl Display for IrAdd {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} + {}", self.left, self.right)
}
}
impl VrUser for IrAdd {
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
[self.left.as_ref(), self.right.as_ref()]
.iter()
.flat_map(|e| e.vr_definitions())
.collect()
}
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
[self.left.as_ref(), self.right.as_ref()]
.iter()
.flat_map(|e| e.vr_uses())
.collect()
}
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
self.left.propagate_spills(spills);
self.right.propagate_spills(spills);
}
fn propagate_register_assignments(
&mut self,
assignments: &HashMap<IrVrVariableDescriptor, usize>,
) {
self.left.propagate_register_assignments(assignments);
self.right.propagate_register_assignments(assignments);
}
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
// no-op, no definitions here
}
}

View File

@ -116,17 +116,8 @@ impl Assemble for IrAssign {
let move_operand = ir_expression.move_operand(constants_table); let move_operand = ir_expression.move_operand(constants_table);
builder.push(Instruction::Move(move_operand, destination)); builder.push(Instruction::Move(move_operand, destination));
} }
IrOperation::Add(ir_add) => { IrOperation::Binary(ir_binary_operation) => {
let (left, right) = ir_add.operand_pair(constants_table); ir_binary_operation.assemble_assign(builder, constants_table, destination);
builder.push(Instruction::Add(left, right, destination));
}
IrOperation::Subtract(ir_subtract) => {
let (left, right) = ir_subtract.operand_pair();
builder.push(Instruction::Subtract(left, right, destination));
}
IrOperation::Multiply(ir_multiply) => {
let (left, right) = ir_multiply.operand_pair();
builder.push(Instruction::Multiply(left, right, destination));
} }
IrOperation::Call(ir_call) => { IrOperation::Call(ir_call) => {
ir_call.assemble(builder, constants_table); ir_call.assemble(builder, constants_table);

View File

@ -0,0 +1,107 @@
use crate::constants_table::ConstantsTable;
use crate::ir::assemble::InstructionsBuilder;
use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_variable::IrVrVariableDescriptor;
use crate::ir::register_allocation::{OffsetCounter, VrUser};
use dvm_lib::instruction::{Instruction, Location};
use std::collections::{HashMap, HashSet};
use std::fmt::{Display, Formatter};
pub enum IrBinaryOperator {
Multiply,
Divide,
Add,
Subtract,
}
pub struct IrBinaryOperation {
left: Box<IrExpression>,
right: Box<IrExpression>,
op: IrBinaryOperator,
}
impl IrBinaryOperation {
pub fn new(left: IrExpression, right: IrExpression, op: IrBinaryOperator) -> Self {
Self {
left: left.into(),
right: right.into(),
op,
}
}
pub fn assemble_assign(
&self,
builder: &mut InstructionsBuilder,
constants_table: &mut ConstantsTable,
destination: Location,
) {
let instruction = match &self.op {
IrBinaryOperator::Multiply => Instruction::Multiply(
self.left.multiply_operand(),
self.right.multiply_operand(),
destination,
),
IrBinaryOperator::Divide => {
todo!()
}
IrBinaryOperator::Add => Instruction::Add(
self.left.add_operand(constants_table),
self.right.add_operand(constants_table),
destination,
),
IrBinaryOperator::Subtract => Instruction::Subtract(
self.left.subtract_operand(),
self.right.subtract_operand(),
destination,
),
};
builder.push(instruction);
}
}
impl Display for IrBinaryOperation {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match &self.op {
IrBinaryOperator::Multiply => {
write!(f, "{} * {}", self.left, self.right)
}
IrBinaryOperator::Divide => {
write!(f, "{} / {}", self.left, self.right)
}
IrBinaryOperator::Add => {
write!(f, "{} + {}", self.left, self.right)
}
IrBinaryOperator::Subtract => {
write!(f, "{} - {}", self.left, self.right)
}
}
}
}
impl VrUser for IrBinaryOperation {
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
todo!()
}
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
[self.left.as_ref(), self.right.as_ref()]
.iter()
.flat_map(|e| e.vr_uses())
.collect()
}
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
todo!()
}
fn propagate_register_assignments(
&mut self,
assignments: &HashMap<IrVrVariableDescriptor, usize>,
) {
todo!()
}
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
todo!()
}
}

View File

@ -1,67 +0,0 @@
use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_variable::IrVrVariableDescriptor;
use crate::ir::register_allocation::{OffsetCounter, VrUser};
use dvm_lib::instruction::MultiplyOperand;
use std::collections::{HashMap, HashSet};
use std::fmt::{Display, Formatter};
pub struct IrMultiply {
left: Box<IrExpression>,
right: Box<IrExpression>,
}
impl IrMultiply {
pub fn new(left: IrExpression, right: IrExpression) -> Self {
Self {
left: left.into(),
right: right.into(),
}
}
pub fn operand_pair(&self) -> (MultiplyOperand, MultiplyOperand) {
(self.left.multiply_operand(), self.right.multiply_operand())
}
}
impl Display for IrMultiply {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} * {}", self.left, self.right)
}
}
impl VrUser for IrMultiply {
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
[&self.left, &self.right]
.iter()
.flat_map(|ir_expression| ir_expression.vr_definitions())
.collect()
}
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
[&self.left, &self.right]
.iter()
.flat_map(|ir_expression| ir_expression.vr_uses())
.collect()
}
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
[&mut self.left, &mut self.right]
.iter_mut()
.for_each(|ir_expression| ir_expression.propagate_spills(spills));
}
fn propagate_register_assignments(
&mut self,
assignments: &HashMap<IrVrVariableDescriptor, usize>,
) {
[&mut self.left, &mut self.right]
.iter_mut()
.for_each(|ir_expression| ir_expression.propagate_register_assignments(assignments));
}
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
[&mut self.left, &mut self.right]
.iter_mut()
.for_each(|ir_expression| ir_expression.propagate_stack_offsets(counter));
}
}

View File

@ -1,12 +1,10 @@
use crate::ir::ir_add::IrAdd;
use crate::ir::ir_allocate::IrAllocate; use crate::ir::ir_allocate::IrAllocate;
use crate::ir::ir_binary_operation::IrBinaryOperation;
use crate::ir::ir_call::IrCall; use crate::ir::ir_call::IrCall;
use crate::ir::ir_expression::IrExpression; use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_get_field_ref::IrGetFieldRef; use crate::ir::ir_get_field_ref::IrGetFieldRef;
use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut; use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut;
use crate::ir::ir_multiply::IrMultiply;
use crate::ir::ir_read_field::IrReadField; use crate::ir::ir_read_field::IrReadField;
use crate::ir::ir_subtract::IrSubtract;
use crate::ir::ir_variable::IrVrVariableDescriptor; use crate::ir::ir_variable::IrVrVariableDescriptor;
use crate::ir::register_allocation::{OffsetCounter, VrUser}; use crate::ir::register_allocation::{OffsetCounter, VrUser};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
@ -17,9 +15,7 @@ pub enum IrOperation {
GetFieldRefMut(IrGetFieldRefMut), GetFieldRefMut(IrGetFieldRefMut),
ReadField(IrReadField), ReadField(IrReadField),
Load(IrExpression), Load(IrExpression),
Add(IrAdd), Binary(IrBinaryOperation),
Subtract(IrSubtract),
Multiply(IrMultiply),
Call(IrCall), Call(IrCall),
Allocate(IrAllocate), Allocate(IrAllocate),
} }
@ -39,14 +35,8 @@ impl Display for IrOperation {
IrOperation::Load(ir_expression) => { IrOperation::Load(ir_expression) => {
write!(f, "{}", ir_expression) write!(f, "{}", ir_expression)
} }
IrOperation::Add(ir_add) => { IrOperation::Binary(ir_binary_operation) => {
write!(f, "{}", ir_add) write!(f, "{}", ir_binary_operation)
}
IrOperation::Subtract(ir_subtract) => {
write!(f, "{}", ir_subtract)
}
IrOperation::Multiply(ir_multiply) => {
write!(f, "{}", ir_multiply)
} }
IrOperation::Call(ir_call) => { IrOperation::Call(ir_call) => {
write!(f, "{}", ir_call) write!(f, "{}", ir_call)
@ -60,17 +50,7 @@ impl Display for IrOperation {
impl VrUser for IrOperation { impl VrUser for IrOperation {
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> { fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
match self { HashSet::new()
IrOperation::GetFieldRef(_) => HashSet::new(),
IrOperation::GetFieldRefMut(_) => HashSet::new(),
IrOperation::ReadField(_) => HashSet::new(),
IrOperation::Load(ir_expression) => ir_expression.vr_definitions(),
IrOperation::Add(ir_add) => ir_add.vr_definitions(),
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_definitions(),
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_definitions(),
IrOperation::Call(ir_call) => ir_call.vr_definitions(),
IrOperation::Allocate(_) => HashSet::new(),
}
} }
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> { fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
@ -79,63 +59,21 @@ impl VrUser for IrOperation {
IrOperation::GetFieldRefMut(ir_get_field_ref_mut) => ir_get_field_ref_mut.vr_uses(), IrOperation::GetFieldRefMut(ir_get_field_ref_mut) => ir_get_field_ref_mut.vr_uses(),
IrOperation::ReadField(ir_read_field) => ir_read_field.vr_uses(), IrOperation::ReadField(ir_read_field) => ir_read_field.vr_uses(),
IrOperation::Load(ir_expression) => ir_expression.vr_uses(), IrOperation::Load(ir_expression) => ir_expression.vr_uses(),
IrOperation::Add(ir_add) => ir_add.vr_uses(), IrOperation::Binary(ir_binary) => ir_binary.vr_uses(),
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_uses(),
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_uses(),
IrOperation::Call(ir_call) => ir_call.vr_uses(), IrOperation::Call(ir_call) => ir_call.vr_uses(),
IrOperation::Allocate(_) => HashSet::new(), IrOperation::Allocate(_) => HashSet::new(),
} }
} }
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) { fn propagate_spills(&mut self, _spills: &HashSet<IrVrVariableDescriptor>) {
match self { // no-op
IrOperation::GetFieldRef(_) => {}
IrOperation::GetFieldRefMut(_) => {}
IrOperation::ReadField(_) => {}
IrOperation::Load(ir_expression) => {
ir_expression.propagate_spills(spills);
}
IrOperation::Add(ir_add) => {
ir_add.propagate_spills(spills);
}
IrOperation::Subtract(ir_subtract) => {
ir_subtract.propagate_spills(spills);
}
IrOperation::Multiply(ir_multiply) => {
ir_multiply.propagate_spills(spills);
}
IrOperation::Call(ir_call) => {
ir_call.propagate_spills(spills);
}
IrOperation::Allocate(_) => (),
}
} }
fn propagate_register_assignments( fn propagate_register_assignments(
&mut self, &mut self,
assignments: &HashMap<IrVrVariableDescriptor, usize>, _assignments: &HashMap<IrVrVariableDescriptor, usize>,
) { ) {
match self { // no-op
IrOperation::GetFieldRef(_) => {}
IrOperation::GetFieldRefMut(_) => {}
IrOperation::ReadField(_) => {}
IrOperation::Load(ir_expression) => {
ir_expression.propagate_register_assignments(assignments);
}
IrOperation::Add(ir_add) => {
ir_add.propagate_register_assignments(assignments);
}
IrOperation::Subtract(ir_subtract) => {
ir_subtract.propagate_register_assignments(assignments);
}
IrOperation::Multiply(ir_multiply) => {
ir_multiply.propagate_register_assignments(assignments);
}
IrOperation::Call(ir_call) => {
ir_call.propagate_register_assignments(assignments);
}
IrOperation::Allocate(_) => (),
}
} }
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) { fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {

View File

@ -1,63 +0,0 @@
use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_variable::IrVrVariableDescriptor;
use crate::ir::register_allocation::{OffsetCounter, VrUser};
use dvm_lib::instruction::SubtractOperand;
use std::collections::{HashMap, HashSet};
use std::fmt::{Display, Formatter};
pub struct IrSubtract {
left: Box<IrExpression>,
right: Box<IrExpression>,
}
impl IrSubtract {
pub fn new(left: IrExpression, right: IrExpression) -> Self {
Self {
left: left.into(),
right: right.into(),
}
}
pub fn operand_pair(&self) -> (SubtractOperand, SubtractOperand) {
(self.left.subtract_operand(), self.right.subtract_operand())
}
}
impl VrUser for IrSubtract {
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
[&self.left, &self.right]
.iter()
.flat_map(|expression| expression.vr_definitions())
.collect()
}
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
[&self.left, &self.right]
.iter()
.flat_map(|expression| expression.vr_uses())
.collect()
}
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
self.left.propagate_spills(spills);
self.right.propagate_spills(spills);
}
fn propagate_register_assignments(
&mut self,
assignments: &HashMap<IrVrVariableDescriptor, usize>,
) {
self.left.propagate_register_assignments(assignments);
self.right.propagate_register_assignments(assignments);
}
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
// no-op
}
}
impl Display for IrSubtract {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} - {}", self.left, self.right)
}
}

View File

@ -1,7 +1,7 @@
mod assemble; mod assemble;
pub mod ir_add;
pub mod ir_allocate; pub mod ir_allocate;
pub mod ir_assign; pub mod ir_assign;
pub mod ir_binary_operation;
pub mod ir_block; pub mod ir_block;
pub mod ir_call; pub mod ir_call;
pub mod ir_class; pub mod ir_class;
@ -9,7 +9,6 @@ pub mod ir_expression;
pub mod ir_function; pub mod ir_function;
pub mod ir_get_field_ref; pub mod ir_get_field_ref;
pub mod ir_get_field_ref_mut; pub mod ir_get_field_ref_mut;
pub mod ir_multiply;
pub mod ir_operation; pub mod ir_operation;
pub mod ir_parameter; pub mod ir_parameter;
pub mod ir_parameter_or_variable; pub mod ir_parameter_or_variable;
@ -17,7 +16,6 @@ pub mod ir_read_field;
pub mod ir_return; pub mod ir_return;
pub mod ir_set_field; pub mod ir_set_field;
pub mod ir_statement; pub mod ir_statement;
pub mod ir_subtract;
pub mod ir_variable; pub mod ir_variable;
mod register_allocation; mod register_allocation;
mod util; mod util;