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::diagnostic::Diagnostic;
use crate::error_codes::BINARY_INCOMPATIBLE_TYPES;
use crate::ir::ir_add::IrAdd;
use crate::ir::ir_assign::IrAssign;
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_operation::IrOperation;
use crate::ir::ir_statement::IrStatement;
use crate::ir::ir_subtract::IrSubtract;
use crate::ir::ir_variable::IrVariable;
use crate::source_range::SourceRange;
use crate::symbol_table::SymbolTable;
@ -179,16 +178,17 @@ impl BinaryExpression {
.rhs
.to_ir_expression(builder, symbol_table)
.expect("Attempt to use a non-value expression in binary expression.");
match self.op {
let ir_binary_operation = match self.op {
BinaryOperation::Multiply => {
todo!()
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Multiply)
}
BinaryOperation::Divide => {
todo!()
BinaryOperation::Divide => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Divide),
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(

View File

@ -2,8 +2,8 @@ use crate::ast::expression::Expression;
use crate::ast::ir_builder::IrBuilder;
use crate::diagnostic::Diagnostic;
use crate::ir::ir_assign::IrAssign;
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_multiply::IrMultiply;
use crate::ir::ir_operation::IrOperation;
use crate::ir::ir_statement::IrStatement;
use crate::ir::ir_variable::IrVariable;
@ -87,8 +87,11 @@ impl NegativeExpression {
_ => panic!("Trying to multiply with a non-integer/double"),
};
let operation =
IrOperation::Multiply(IrMultiply::new(IrExpression::Parameter(parameter), rhs));
let operation = IrOperation::Binary(IrBinaryOperation::new(
IrExpression::Parameter(parameter),
rhs,
IrBinaryOperator::Multiply,
));
let assign = IrAssign::new(destination.clone(), operation);
builder
@ -110,8 +113,11 @@ impl NegativeExpression {
_ => panic!("Trying to multiply with a non-integer/double"),
};
let operation =
IrOperation::Multiply(IrMultiply::new(IrExpression::Variable(variable), rhs));
let operation = IrOperation::Binary(IrBinaryOperation::new(
IrExpression::Variable(variable),
rhs,
IrBinaryOperator::Multiply,
));
let assign = IrAssign::new(destination.clone(), operation);
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);
builder.push(Instruction::Move(move_operand, destination));
}
IrOperation::Add(ir_add) => {
let (left, right) = ir_add.operand_pair(constants_table);
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::Binary(ir_binary_operation) => {
ir_binary_operation.assemble_assign(builder, constants_table, destination);
}
IrOperation::Call(ir_call) => {
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_binary_operation::IrBinaryOperation;
use crate::ir::ir_call::IrCall;
use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_get_field_ref::IrGetFieldRef;
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_subtract::IrSubtract;
use crate::ir::ir_variable::IrVrVariableDescriptor;
use crate::ir::register_allocation::{OffsetCounter, VrUser};
use std::collections::{HashMap, HashSet};
@ -17,9 +15,7 @@ pub enum IrOperation {
GetFieldRefMut(IrGetFieldRefMut),
ReadField(IrReadField),
Load(IrExpression),
Add(IrAdd),
Subtract(IrSubtract),
Multiply(IrMultiply),
Binary(IrBinaryOperation),
Call(IrCall),
Allocate(IrAllocate),
}
@ -39,14 +35,8 @@ impl Display for IrOperation {
IrOperation::Load(ir_expression) => {
write!(f, "{}", ir_expression)
}
IrOperation::Add(ir_add) => {
write!(f, "{}", ir_add)
}
IrOperation::Subtract(ir_subtract) => {
write!(f, "{}", ir_subtract)
}
IrOperation::Multiply(ir_multiply) => {
write!(f, "{}", ir_multiply)
IrOperation::Binary(ir_binary_operation) => {
write!(f, "{}", ir_binary_operation)
}
IrOperation::Call(ir_call) => {
write!(f, "{}", ir_call)
@ -60,17 +50,7 @@ impl Display for IrOperation {
impl VrUser for IrOperation {
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
match self {
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(),
}
HashSet::new()
}
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::ReadField(ir_read_field) => ir_read_field.vr_uses(),
IrOperation::Load(ir_expression) => ir_expression.vr_uses(),
IrOperation::Add(ir_add) => ir_add.vr_uses(),
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_uses(),
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_uses(),
IrOperation::Binary(ir_binary) => ir_binary.vr_uses(),
IrOperation::Call(ir_call) => ir_call.vr_uses(),
IrOperation::Allocate(_) => HashSet::new(),
}
}
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
match self {
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_spills(&mut self, _spills: &HashSet<IrVrVariableDescriptor>) {
// no-op
}
fn propagate_register_assignments(
&mut self,
assignments: &HashMap<IrVrVariableDescriptor, usize>,
_assignments: &HashMap<IrVrVariableDescriptor, usize>,
) {
match self {
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(_) => (),
}
// no-op
}
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;
pub mod ir_add;
pub mod ir_allocate;
pub mod ir_assign;
pub mod ir_binary_operation;
pub mod ir_block;
pub mod ir_call;
pub mod ir_class;
@ -9,7 +9,6 @@ pub mod ir_expression;
pub mod ir_function;
pub mod ir_get_field_ref;
pub mod ir_get_field_ref_mut;
pub mod ir_multiply;
pub mod ir_operation;
pub mod ir_parameter;
pub mod ir_parameter_or_variable;
@ -17,7 +16,6 @@ pub mod ir_read_field;
pub mod ir_return;
pub mod ir_set_field;
pub mod ir_statement;
pub mod ir_subtract;
pub mod ir_variable;
mod register_allocation;
mod util;