miden_assembly/instruction/
procedures.rs1use alloc::vec::Vec;
2
3use miden_assembly_syntax::{
4 Word,
5 ast::{InvocationTarget, InvokeKind},
6 diagnostics::Report,
7};
8use miden_core::operations::{AssemblyOp, Operation};
9use miden_mast_package::debug_info::DebugSourceInlineCall;
10use smallvec::SmallVec;
11
12use crate::{
13 Assembler, GlobalItemIndex,
14 basic_block_builder::BasicBlockBuilder,
15 mast_forest_builder::{MastForestBuilder, MastNodeUse},
16};
17
18impl Assembler {
20 pub(super) fn invoke(
26 &self,
27 kind: InvokeKind,
28 callee: &InvocationTarget,
29 caller: GlobalItemIndex,
30 mast_forest_builder: &mut MastForestBuilder,
31 asm_op: Option<AssemblyOp>,
32 inline_calls: Vec<DebugSourceInlineCall>,
33 ) -> Result<MastNodeUse, Report> {
34 let resolved = self.resolve_target(kind, callee, caller.module, mast_forest_builder)?;
35
36 match kind {
37 InvokeKind::ProcRef => Ok(resolved.node),
38 InvokeKind::Exec => {
39 mast_forest_builder.record_exec_inline_calls(resolved.node, &inline_calls)
40 },
41 InvokeKind::Call | InvokeKind::SysCall => mast_forest_builder.ensure_call_node_use(
42 resolved.node,
43 matches!(kind, InvokeKind::SysCall),
44 asm_op.expect("call and syscall invocations must provide an AssemblyOp"),
45 inline_calls,
46 ),
47 }
48 }
49
50 pub(super) fn dynexec(
52 &self,
53 mast_forest_builder: &mut MastForestBuilder,
54 asm_op: AssemblyOp,
55 inline_calls: Vec<DebugSourceInlineCall>,
56 ) -> Result<Option<MastNodeUse>, Report> {
57 let dyn_node_ref = mast_forest_builder.ensure_dyn_node_use(false, asm_op, inline_calls)?;
58
59 Ok(Some(dyn_node_ref))
60 }
61
62 pub(super) fn dyncall(
64 &self,
65 mast_forest_builder: &mut MastForestBuilder,
66 asm_op: AssemblyOp,
67 inline_calls: Vec<DebugSourceInlineCall>,
68 ) -> Result<Option<MastNodeUse>, Report> {
69 let dyn_call_node_ref =
70 mast_forest_builder.ensure_dyn_node_use(true, asm_op, inline_calls)?;
71
72 Ok(Some(dyn_call_node_ref))
73 }
74
75 pub(super) fn procref(
76 &self,
77 callee: &InvocationTarget,
78 caller: GlobalItemIndex,
79 block_builder: &mut BasicBlockBuilder,
80 ) -> Result<(), Report> {
81 let mast_root = {
82 let resolved = self.resolve_target(
83 InvokeKind::ProcRef,
84 callee,
85 caller.module,
86 block_builder.mast_forest_builder_mut(),
87 )?;
88 block_builder
91 .mast_forest_builder()
92 .mast_root_for_ref(resolved.node.node_ref())
93 .unwrap()
94 };
95
96 self.procref_mast_root(mast_root, block_builder);
97 Ok(())
98 }
99
100 fn procref_mast_root(&self, mast_root: Word, block_builder: &mut BasicBlockBuilder) {
101 let ops = mast_root
104 .iter()
105 .rev()
106 .map(|elem| Operation::Push(*elem))
107 .collect::<SmallVec<[_; 4]>>();
108 block_builder.push_ops(ops);
109 }
110}