deimos-lang/dmc-lib/src/ir/ir_call.rs

97 lines
2.8 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::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_platform() {
builder.push(Instruction::InvokePlatformStatic(
symbol.name_owned(),
symbol.parameters().len(),
));
} else {
builder.push(Instruction::InvokeStatic(
symbol.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(())
}
}