miden_assembly/assembler/instruction/
procedures.rsuse smallvec::SmallVec;
use vm_core::mast::MastNodeId;
use super::{Assembler, BasicBlockBuilder, Operation};
use crate::{
assembler::{mast_forest_builder::MastForestBuilder, ProcedureContext},
ast::{InvocationTarget, InvokeKind},
AssemblyError, RpoDigest,
};
impl Assembler {
pub(super) fn invoke(
&self,
kind: InvokeKind,
callee: &InvocationTarget,
proc_ctx: &ProcedureContext,
mast_forest_builder: &mut MastForestBuilder,
) -> Result<MastNodeId, AssemblyError> {
let invoked_proc_node_id =
self.resolve_target(kind, callee, proc_ctx, mast_forest_builder)?;
match kind {
InvokeKind::ProcRef | InvokeKind::Exec => Ok(invoked_proc_node_id),
InvokeKind::Call => mast_forest_builder.ensure_call(invoked_proc_node_id),
InvokeKind::SysCall => mast_forest_builder.ensure_syscall(invoked_proc_node_id),
}
}
pub(super) fn dynexec(
&self,
mast_forest_builder: &mut MastForestBuilder,
) -> Result<Option<MastNodeId>, AssemblyError> {
let dyn_node_id = mast_forest_builder.ensure_dyn()?;
Ok(Some(dyn_node_id))
}
pub(super) fn dyncall(
&self,
mast_forest_builder: &mut MastForestBuilder,
) -> Result<Option<MastNodeId>, AssemblyError> {
let dyn_call_node_id = mast_forest_builder.ensure_dyncall()?;
Ok(Some(dyn_call_node_id))
}
pub(super) fn procref(
&self,
callee: &InvocationTarget,
proc_ctx: &mut ProcedureContext,
block_builder: &mut BasicBlockBuilder,
) -> Result<(), AssemblyError> {
let mast_root = {
let proc_body_id = self.resolve_target(
InvokeKind::ProcRef,
callee,
proc_ctx,
block_builder.mast_forest_builder_mut(),
)?;
block_builder
.mast_forest_builder()
.get_mast_node(proc_body_id)
.unwrap()
.digest()
};
self.procref_mast_root(mast_root, block_builder)
}
fn procref_mast_root(
&self,
mast_root: RpoDigest,
block_builder: &mut BasicBlockBuilder,
) -> Result<(), AssemblyError> {
let ops = mast_root
.iter()
.map(|elem| Operation::Push(*elem))
.collect::<SmallVec<[_; 4]>>();
block_builder.push_ops(ops);
Ok(())
}
}