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::VrUser; use dvm_lib::instruction::{Instruction, Location}; use std::collections::HashSet; use std::fmt::{Display, Formatter}; pub enum IrBinaryOperator { Multiply, Divide, Add, Subtract, } pub struct IrBinaryOperation { left: Box, right: Box, 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_uses(&self) -> HashSet { [self.left.as_ref(), self.right.as_ref()] .iter() .flat_map(|e| e.vr_uses()) .collect() } }