127 lines
4.4 KiB
Rust
127 lines
4.4 KiB
Rust
use crate::constants_table::ConstantsTable;
|
|
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
|
use crate::ir::ir_operation::IrOperation;
|
|
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
|
use crate::ir::register_allocation::VrUser;
|
|
use crate::ir::util::propagate_spills;
|
|
use crate::offset_counter::OffsetCounter;
|
|
use dvm_lib::instruction::Instruction;
|
|
use std::cell::RefCell;
|
|
use std::collections::{HashMap, HashSet};
|
|
use std::fmt::{Display, Formatter};
|
|
use std::rc::Rc;
|
|
|
|
pub struct IrAssign {
|
|
destination: Rc<RefCell<IrVariable>>,
|
|
initializer: Box<IrOperation>,
|
|
}
|
|
|
|
impl IrAssign {
|
|
pub fn new(destination: Rc<RefCell<IrVariable>>, initializer: IrOperation) -> Self {
|
|
Self {
|
|
destination,
|
|
initializer: initializer.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl VrUser for IrAssign {
|
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
|
self.destination
|
|
.borrow()
|
|
.descriptor()
|
|
.vr_variable_descriptors()
|
|
}
|
|
|
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
|
self.initializer.vr_uses()
|
|
}
|
|
|
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
|
propagate_spills(&mut self.destination, spills);
|
|
}
|
|
|
|
fn propagate_register_assignments(
|
|
&mut self,
|
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
|
) {
|
|
let mut borrowed_destination = self.destination.borrow_mut();
|
|
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
|
borrowed_destination.descriptor_mut()
|
|
{
|
|
if assignments.contains_key(vr_variable) {
|
|
vr_variable.set_assigned_register(assignments[vr_variable]);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
|
|
let mut borrowed_destination = self.destination.borrow_mut();
|
|
if let IrVariableDescriptor::Stack(stack_variable) = borrowed_destination.descriptor_mut() {
|
|
stack_variable.use_next_offset(counter);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Assemble for IrAssign {
|
|
fn assemble(&self, builder: &mut InstructionsBuilder, constants_table: &mut ConstantsTable) {
|
|
let destination = self.destination.borrow().descriptor().as_location();
|
|
|
|
match self.initializer.as_ref() {
|
|
IrOperation::GetFieldRef(ir_get_field_ref) => {
|
|
let self_location = ir_get_field_ref.self_parameter_or_variable().as_location();
|
|
builder.push(Instruction::GetFieldPointer(
|
|
self_location,
|
|
ir_get_field_ref.field_index(),
|
|
destination,
|
|
));
|
|
}
|
|
IrOperation::GetFieldRefMut(ir_get_field_ref_mut) => {
|
|
let self_location = ir_get_field_ref_mut
|
|
.self_parameter_or_variable()
|
|
.as_location();
|
|
builder.push(Instruction::GetFieldPointerMut(
|
|
self_location,
|
|
ir_get_field_ref_mut.field_index(),
|
|
destination,
|
|
));
|
|
}
|
|
IrOperation::ReadField(ir_read_field) => {
|
|
let field_ref_location = ir_read_field
|
|
.field_ref_variable()
|
|
.borrow()
|
|
.descriptor()
|
|
.as_location();
|
|
builder.push(Instruction::ReadField(field_ref_location, destination));
|
|
}
|
|
IrOperation::Load(ir_expression) => {
|
|
let move_operand = ir_expression.move_operand(constants_table);
|
|
builder.push(Instruction::Move(move_operand, 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);
|
|
builder.push(Instruction::Pop(Some(destination)));
|
|
}
|
|
IrOperation::Allocate(ir_allocate) => builder.push(Instruction::Allocate(
|
|
ir_allocate.class_fqn_owned(),
|
|
destination,
|
|
)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for IrAssign {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}: {} = {}",
|
|
self.destination.borrow(),
|
|
self.destination.borrow().type_info(),
|
|
self.initializer
|
|
)
|
|
}
|
|
}
|