98 lines
2.9 KiB
Rust
98 lines
2.9 KiB
Rust
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<str>,
|
|
arguments: Vec<IrExpression>,
|
|
function_symbol: Rc<RefCell<FunctionSymbol>>,
|
|
}
|
|
|
|
impl IrCall {
|
|
pub fn new(
|
|
function_name: Rc<str>,
|
|
arguments: Vec<IrExpression>,
|
|
function_symbol: Rc<RefCell<FunctionSymbol>>,
|
|
) -> Self {
|
|
Self {
|
|
function_name,
|
|
arguments,
|
|
function_symbol,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl VrUser for IrCall {
|
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
|
HashSet::new()
|
|
}
|
|
|
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
|
self.arguments.iter().flat_map(|a| a.vr_uses()).collect()
|
|
}
|
|
|
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
|
for argument in &mut self.arguments {
|
|
argument.propagate_spills(spills);
|
|
}
|
|
}
|
|
|
|
fn propagate_register_assignments(
|
|
&mut self,
|
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
|
) {
|
|
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(())
|
|
}
|
|
}
|