use crate::constants_table::ConstantsTable; use crate::ir::assemble::{Assemble, InstructionsBuilder}; use crate::ir::ir_expression::IrExpression; use crate::ir::ir_variable::IrVrVariableDescriptor; use crate::ir::register_allocation::{OffsetCounter, VrUser}; use crate::symbol::Symbol; use crate::symbol::function_symbol::FunctionSymbol; 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 IrCall { function_name: Rc, arguments: Vec, function_symbol: Rc>, } impl IrCall { pub fn new( function_name: Rc, arguments: Vec, function_symbol: Rc>, ) -> Self { Self { function_name, arguments, function_symbol, } } } impl VrUser for IrCall { fn vr_definitions(&self) -> HashSet { HashSet::new() } fn vr_uses(&self) -> HashSet { self.arguments.iter().flat_map(|a| a.vr_uses()).collect() } fn propagate_spills(&mut self, spills: &HashSet) { for argument in &mut self.arguments { argument.propagate_spills(spills); } } fn propagate_register_assignments( &mut self, assignments: &HashMap, ) { for argument in &mut self.arguments { argument.propagate_register_assignments(assignments); } } fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) { // no-op, because no definitions here } } impl Assemble for IrCall { fn assemble(&self, builder: &mut InstructionsBuilder, constants_table: &mut ConstantsTable) { // push all args self.arguments .iter() .map(|ir_expression| ir_expression.push_operand(constants_table)) .for_each(|push_operand| builder.push(Instruction::Push(push_operand))); let symbol = self.function_symbol.borrow(); if symbol.is_extern() { builder.push(Instruction::InvokePlatformStatic( symbol.declared_name_owned(), symbol.parameters().len(), )); } else { builder.push(Instruction::InvokeStatic( symbol.declared_name_owned(), symbol.parameters().len(), )); } } } impl Display for IrCall { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}(", self.function_name)?; for (i, argument) in self.arguments.iter().enumerate() { write!(f, "{}", argument)?; if i < self.arguments.len() - 1 { write!(f, ", ")?; } } write!(f, ")")?; Ok(()) } }