1use std::{collections::BTreeSet, fmt};
2
3use cranelift_entity::entity_impl;
4pub use miden_assembly::ast::{AdviceInjectorNode, DebugOptions};
5use smallvec::{smallvec, SmallVec};
6
7use crate::{
8    diagnostics::{SourceSpan, Span},
9    Felt, FunctionIdent, Ident, LocalId,
10};
11
12#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct MasmBlockId(u32);
15entity_impl!(MasmBlockId, "blk");
16
17#[derive(Debug, Clone, PartialEq)]
19pub struct MasmBlock {
20    pub id: MasmBlockId,
21    pub ops: SmallVec<[Span<MasmOp>; 4]>,
22}
23impl MasmBlock {
24    #[inline(always)]
26    pub fn is_empty(&self) -> bool {
27        self.ops.is_empty()
28    }
29
30    #[inline(always)]
32    pub fn ops(&self) -> &[Span<MasmOp>] {
33        self.ops.as_slice()
34    }
35
36    #[inline(always)]
38    pub fn push(&mut self, op: MasmOp, span: SourceSpan) {
39        self.ops.push(Span::new(span, op));
40    }
41
42    #[inline]
44    pub fn push_n(&mut self, count: usize, op: MasmOp, span: SourceSpan) {
45        let op = Span::new(span, op);
46        for _ in 0..count {
47            self.ops.push(op);
48        }
49    }
50
51    #[inline]
53    pub fn push_repeat(&mut self, ops: &[Span<MasmOp>], count: usize) {
54        for _ in 0..count {
55            self.ops.extend_from_slice(ops);
56        }
57    }
58
59    #[inline]
61    pub fn push_template<const N: usize, F>(&mut self, count: usize, template: F)
62    where
63        F: Fn(usize) -> [Span<MasmOp>; N],
64    {
65        for n in 0..count {
66            self.ops.extend_from_slice(&template(n));
67        }
68    }
69
70    #[inline]
72    pub fn extend_from_slice(&mut self, slice: &[Span<MasmOp>]) {
73        self.ops.extend_from_slice(slice);
74    }
75
76    #[inline]
78    pub fn extend(&mut self, ops: impl IntoIterator<Item = Span<MasmOp>>) {
79        self.ops.extend(ops);
80    }
81
82    #[inline]
84    pub fn append<B>(&mut self, other: &mut SmallVec<B>)
85    where
86        B: smallvec::Array<Item = Span<MasmOp>>,
87    {
88        self.ops.append(other);
89    }
90}
91
92#[derive(Debug, Copy, Clone, PartialEq, Eq)]
97pub enum MasmOp {
98    Padw,
100    Push(Felt),
102    Push2([Felt; 2]),
104    Pushw([Felt; 4]),
106    PushU8(u8),
108    PushU16(u16),
110    PushU32(u32),
112    Drop,
114    Dropw,
116    Dup(u8),
120    Dupw(u8),
126    Swap(u8),
130    Swapw(u8),
136    Swapdw,
138    Movup(u8),
142    Movupw(u8),
147    Movdn(u8),
151    Movdnw(u8),
156    Cswap,
161    Cswapw,
166    Cdrop,
170    Cdropw,
175    Assert,
177    AssertWithError(u32),
179    Assertz,
181    AssertzWithError(u32),
183    AssertEq,
185    AssertEqWithError(u32),
187    AssertEqw,
189    AssertEqwWithError(u32),
191    LocAddr(LocalId),
193    LocStore(LocalId),
196    LocStorew(LocalId),
198    LocLoad(LocalId),
201    LocLoadw(LocalId),
203    MemLoad,
208    MemLoadImm(u32),
210    MemLoadw,
215    MemLoadwImm(u32),
217    MemStore,
223    MemStoreImm(u32),
225    MemStorew,
230    MemStorewImm(u32),
232    MemStream,
236    AdvPipe,
242    AdvPush(u8),
248    AdvLoadw,
253    AdvInjectPushU64Div,
259    AdvInjectPushMapVal,
267    AdvInjectPushMapValImm(u8),
276    AdvInjectPushMapValN,
284    AdvInjectPushMapValNImm(u8),
293    AdvInjectPushMTreeNode,
300    AdvInjectInsertMem,
306    AdvInjectInsertHdword,
314    AdvInjectInsertHdwordImm(u8),
324    AdvInjectInsertHperm,
333    AdvInjectPushSignature(miden_assembly::ast::SignatureKind),
335    Hash,
341    Hmerge,
347    Hperm,
356    MtreeGet,
364    MtreeSet,
377    MtreeMerge,
385    MtreeVerify,
394    MtreeVerifyWithError(u32),
404    FriExt2Fold4,
422    RCombBase,
444    Ext2add,
449    Ext2sub,
454    Ext2mul,
459    Ext2neg,
464    Ext2inv,
470    Ext2div,
476    If(MasmBlockId, MasmBlockId),
483    While(MasmBlockId),
489    Repeat(u16, MasmBlockId),
491    Exec(FunctionIdent),
493    Syscall(FunctionIdent),
496    Call(FunctionIdent),
499    DynExec,
502    DynCall,
504    ProcRef(FunctionIdent),
507    Add,
509    AddImm(Felt),
511    Sub,
513    SubImm(Felt),
515    Mul,
517    MulImm(Felt),
519    Div,
523    DivImm(Felt),
525    Neg,
527    Inv,
531    Incr,
533    Ilog2,
535    Pow2,
539    Exp,
543    ExpImm(u8),
547    ExpBitLength(u8),
548    Not,
552    And,
556    AndImm(bool),
560    Or,
564    OrImm(bool),
568    Xor,
572    XorImm(bool),
576    Eq,
578    EqImm(Felt),
580    Neq,
582    NeqImm(Felt),
584    Gt,
586    GtImm(Felt),
588    Gte,
590    GteImm(Felt),
592    Lt,
594    LtImm(Felt),
596    Lte,
598    LteImm(Felt),
600    IsOdd,
602    Eqw,
607    Sdepth,
609    Caller,
612    Clk,
614    U32Test,
616    U32Testw,
619    U32Assert,
621    U32AssertWithError(u32),
623    U32Assert2,
625    U32Assert2WithError(u32),
628    U32Assertw,
630    U32AssertwWithError(u32),
633    U32Cast,
637    U32Split,
641    U32OverflowingAdd,
648    U32OverflowingAddImm(u32),
650    U32WrappingAdd,
654    U32WrappingAddImm(u32),
656    U32OverflowingAdd3,
662    U32WrappingAdd3,
668    U32OverflowingSub,
675    U32OverflowingSubImm(u32),
677    U32WrappingSub,
681    U32WrappingSubImm(u32),
683    U32OverflowingMul,
689    U32OverflowingMulImm(u32),
691    U32WrappingMul,
695    U32WrappingMulImm(u32),
697    U32OverflowingMadd,
703    U32WrappingMadd,
707    U32Div,
713    U32DivImm(u32),
715    U32Mod,
721    U32ModImm(u32),
723    U32DivMod,
729    U32DivModImm(u32),
731    U32And,
735    U32Or,
739    U32Xor,
743    U32Not,
747    U32Shl,
753    U32ShlImm(u32),
755    U32Shr,
761    U32ShrImm(u32),
763    U32Rotl,
768    U32RotlImm(u32),
770    U32Rotr,
775    U32RotrImm(u32),
777    U32Popcnt,
781    U32Clz,
785    U32Ctz,
789    U32Clo,
793    U32Cto,
797    U32Lt,
801    U32LtImm(u32),
803    U32Lte,
807    U32LteImm(u32),
809    U32Gt,
813    U32GtImm(u32),
815    U32Gte,
819    U32GteImm(u32),
821    U32Min,
825    U32MinImm(u32),
827    U32Max,
831    U32MaxImm(u32),
833    Breakpoint,
835    DebugStack,
837    DebugStackN(u8),
839    DebugMemory,
841    DebugMemoryAt(u32),
843    DebugMemoryRange(u32, u32),
845    DebugFrame,
847    DebugFrameAt(u16),
849    DebugFrameRange(u16, u16),
851    Emit(u32),
853    Trace(u32),
855    Nop,
857}
858
859macro_rules! unwrap_imm {
860    ($imm:ident) => {{
861        match $imm {
862            miden_assembly::ast::Immediate::Value(imm) => imm.into_inner(),
863            miden_assembly::ast::Immediate::Constant(id) => {
864                panic!("invalid reference to constant definition: '{id}'")
865            }
866        }
867    }};
868}
869
870macro_rules! unwrap_u32 {
871    ($imm:ident) => {{
872        match $imm {
873            miden_assembly::ast::Immediate::Value(imm) => imm.into_inner(),
874            miden_assembly::ast::Immediate::Constant(id) => {
875                panic!("invalid reference to constant definition: '{id}'")
876            }
877        }
878    }};
879}
880
881macro_rules! unwrap_u16 {
882    ($imm:ident) => {{
883        match $imm {
884            miden_assembly::ast::Immediate::Value(imm) => imm.into_inner(),
885            miden_assembly::ast::Immediate::Constant(id) => {
886                panic!("invalid reference to constant definition: '{id}'")
887            }
888        }
889    }};
890}
891
892macro_rules! unwrap_u8 {
893    ($imm:ident) => {{
894        match $imm {
895            miden_assembly::ast::Immediate::Value(imm) => imm.into_inner(),
896            miden_assembly::ast::Immediate::Constant(id) => {
897                panic!("invalid reference to constant definition: '{id}'")
898            }
899        }
900    }};
901}
902
903impl MasmOp {
904    pub fn has_regions(&self) -> bool {
905        matches!(self, Self::If(_, _) | Self::While(_) | Self::Repeat(_, _))
906    }
907
908    pub fn cost(&self) -> usize {
910        match self {
911            Self::Padw => 4,
912            Self::Push(_) | Self::PushU8(_) | Self::PushU16(_) | Self::PushU32(_) => 1,
913            Self::Push2(_) => 2,
914            Self::Pushw(_) => 4,
915            Self::Drop => 1,
916            Self::Dropw => 4,
917            Self::Dup(8) | Self::Dup(10) | Self::Dup(12) | Self::Dup(14) => 3,
918            Self::Dup(_) => 1,
919            Self::Dupw(_) => 4,
920            Self::Swap(1) => 1,
921            Self::Swap(2..=8) => 2,
922            Self::Swap(_) => 6,
923            Self::Swapw(_) | Self::Swapdw => 1,
924            Self::Movup(2..=8) => 1,
925            Self::Movup(_) => 4,
926            Self::Movupw(2) => 2,
927            Self::Movupw(_) => 3,
928            Self::Movdn(2..=8) => 1,
929            Self::Movdn(_) => 4,
930            Self::Movdnw(2) => 2,
931            Self::Movdnw(_) => 3,
932            Self::Cswap => 1,
933            Self::Cswapw => 1,
934            Self::Cdrop => 2,
935            Self::Cdropw => 5,
936            Self::Assert | Self::AssertWithError(_) => 1,
937            Self::Assertz | Self::AssertzWithError(_) => 2,
938            Self::AssertEq | Self::AssertEqWithError(_) => 2,
939            Self::AssertEqw | Self::AssertEqwWithError(_) => 11,
940            Self::LocAddr(_) => 2,
941            Self::LocStore(id) if id.as_usize() == 1 => 5,
942            Self::LocStore(_) => 4,
943            Self::LocStorew(id) if id.as_usize() == 1 => 4,
944            Self::LocStorew(_) => 3,
945            Self::LocLoad(id) | Self::LocLoadw(id) if id.as_usize() == 1 => 4,
946            Self::LocLoad(_) | Self::LocLoadw(_) => 3,
947            Self::MemLoad | Self::MemLoadw => 1,
948            Self::MemLoadImm(_) | Self::MemLoadwImm(_) => 2,
949            Self::MemStore => 2,
950            Self::MemStoreImm(1) => 4,
951            Self::MemStoreImm(_) => 3,
952            Self::MemStorew => 1,
953            Self::MemStorewImm(1) => 3,
954            Self::MemStorewImm(_) => 2,
955            Self::MemStream => 1,
956            Self::AdvPipe => 1,
957            Self::AdvPush(n) => *n as usize,
958            Self::AdvLoadw => 1,
959            Self::If(..) => 12,
965            Self::While(_) => 12,
968            Self::Repeat(..) => 0,
973            Self::ProcRef(_) => 4,
974            Self::Exec(_) => 2,
975            Self::Call(_) | Self::Syscall(_) => 12,
977            Self::DynExec => 8,
980            Self::DynCall => 16,
982            Self::Add | Self::Sub | Self::Mul => 1,
983            Self::AddImm(imm) => match imm.as_int() {
984                0 => 0,
985                1 => 1,
986                _ => 2,
987            },
988            Self::SubImm(imm) | Self::MulImm(imm) => match imm.as_int() {
989                0 => 0,
990                _ => 2,
991            },
992            Self::Div => 2,
993            Self::DivImm(imm) => match imm.as_int() {
994                1 => 0,
995                _ => 2,
996            },
997            Self::Neg | Self::Inv | Self::Incr => 1,
998            Self::Ilog2 => 44,
999            Self::Pow2 => 16,
1000            Self::Exp => 9 + 32usize.ilog2() as usize,
1003            Self::ExpImm(0) => 3,
1004            Self::ExpImm(1) => 1,
1005            Self::ExpImm(2) => 2,
1006            Self::ExpImm(3) => 4,
1007            Self::ExpImm(4) => 6,
1008            Self::ExpImm(5) => 8,
1009            Self::ExpImm(6) => 10,
1010            Self::ExpImm(7) => 12,
1011            Self::ExpImm(imm) | Self::ExpBitLength(imm) => {
1012                9 + unsafe { f64::from(*imm).log2().ceil().to_int_unchecked::<usize>() }
1013            }
1014            Self::Not | Self::And | Self::Or => 1,
1015            Self::AndImm(_) | Self::OrImm(_) => 2,
1016            Self::Xor => 7,
1017            Self::XorImm(_) => 8,
1018            Self::Eq => 1,
1019            Self::EqImm(imm) => match imm.as_int() {
1020                0 => 1,
1021                _ => 2,
1022            },
1023            Self::Neq => 2,
1024            Self::NeqImm(imm) => match imm.as_int() {
1025                0 => 1,
1026                _ => 3,
1027            },
1028            Self::Gt => 15,
1029            Self::GtImm(_) => 16,
1030            Self::Gte => 16,
1031            Self::GteImm(_) => 17,
1032            Self::Lt => 14,
1033            Self::LtImm(_) => 15,
1034            Self::Lte => 15,
1035            Self::LteImm(_) => 16,
1036            Self::IsOdd => 5,
1037            Self::Eqw => 15,
1038            Self::Hash => 20,
1039            Self::Hmerge => 16,
1040            Self::Hperm => 1,
1041            Self::MtreeGet => 9,
1042            Self::MtreeSet => 29,
1043            Self::MtreeMerge => 16,
1044            Self::MtreeVerify | Self::MtreeVerifyWithError(_) => 1,
1045            Self::FriExt2Fold4 | Self::RCombBase => 50,
1047            Self::Ext2add => 5,
1048            Self::Ext2sub => 7,
1049            Self::Ext2mul => 3,
1050            Self::Ext2neg => 4,
1051            Self::Ext2inv => 8,
1052            Self::Ext2div => 11,
1053            Self::Clk | Self::Caller | Self::Sdepth => 1,
1054            Self::U32Test => 5,
1055            Self::U32Testw => 23,
1056            Self::U32Assert | Self::U32AssertWithError(_) => 3,
1057            Self::U32Assert2 | Self::U32Assert2WithError(_) => 1,
1058            Self::U32Assertw | Self::U32AssertwWithError(_) => 6,
1059            Self::U32Cast => 2,
1060            Self::U32Split => 1,
1061            Self::U32OverflowingAdd => 1,
1062            Self::U32OverflowingAddImm(_) => 2,
1063            Self::U32WrappingAdd => 2,
1064            Self::U32WrappingAddImm(_) => 3,
1065            Self::U32OverflowingAdd3 => 1,
1066            Self::U32WrappingAdd3 => 2,
1067            Self::U32OverflowingSub => 1,
1068            Self::U32OverflowingSubImm(_) => 2,
1069            Self::U32WrappingSub => 2,
1070            Self::U32WrappingSubImm(_) => 3,
1071            Self::U32OverflowingMul => 1,
1072            Self::U32OverflowingMulImm(_) => 2,
1073            Self::U32WrappingMul => 2,
1074            Self::U32WrappingMulImm(_) => 3,
1075            Self::U32OverflowingMadd => 1,
1076            Self::U32WrappingMadd => 2,
1077            Self::U32Div => 2,
1078            Self::U32DivImm(_) => 3,
1079            Self::U32Mod => 3,
1080            Self::U32ModImm(_) => 4,
1081            Self::U32DivMod => 1,
1082            Self::U32DivModImm(_) => 2,
1083            Self::U32And => 1,
1084            Self::U32Or => 6,
1085            Self::U32Xor => 1,
1086            Self::U32Not => 5,
1087            Self::U32Shl => 18,
1088            Self::U32ShlImm(0) => 0,
1089            Self::U32ShlImm(_) => 3,
1090            Self::U32Shr => 18,
1091            Self::U32ShrImm(0) => 0,
1092            Self::U32ShrImm(_) => 3,
1093            Self::U32Rotl => 18,
1094            Self::U32RotlImm(0) => 0,
1095            Self::U32RotlImm(_) => 3,
1096            Self::U32Rotr => 22,
1097            Self::U32RotrImm(0) => 0,
1098            Self::U32RotrImm(_) => 3,
1099            Self::U32Popcnt => 33,
1100            Self::U32Clz => 37,
1101            Self::U32Ctz => 34,
1102            Self::U32Clo => 36,
1103            Self::U32Cto => 33,
1104            Self::U32Lt => 3,
1105            Self::U32LtImm(_) => 4,
1106            Self::U32Lte => 5,
1107            Self::U32LteImm(_) => 6,
1108            Self::U32Gt => 4,
1109            Self::U32GtImm(_) => 5,
1110            Self::U32Gte => 4,
1111            Self::U32GteImm(_) => 5,
1112            Self::U32Min => 8,
1113            Self::U32MinImm(_) => 9,
1114            Self::U32Max => 9,
1115            Self::U32MaxImm(_) => 10,
1116            Self::Emit(_)
1119            | Self::Trace(_)
1120            | Self::AdvInjectPushU64Div
1121            | Self::AdvInjectPushMapVal
1122            | Self::AdvInjectPushMapValImm(_)
1123            | Self::AdvInjectPushMapValN
1124            | Self::AdvInjectPushMapValNImm(_)
1125            | Self::AdvInjectPushMTreeNode
1126            | Self::AdvInjectInsertMem
1127            | Self::AdvInjectInsertHdword
1128            | Self::AdvInjectInsertHdwordImm(_)
1129            | Self::AdvInjectInsertHperm
1130            | Self::AdvInjectPushSignature(_)
1131            | Self::DebugStack
1132            | Self::DebugStackN(_)
1133            | Self::DebugMemory
1134            | Self::DebugMemoryAt(_)
1135            | Self::DebugMemoryRange(..)
1136            | Self::DebugFrame
1137            | Self::DebugFrameAt(_)
1138            | Self::DebugFrameRange(..)
1139            | Self::Breakpoint
1140            | Self::Nop => 0,
1141        }
1142    }
1143
1144    pub fn from_masm(
1145        current_module: Ident,
1146        ix: miden_assembly::ast::Instruction,
1147    ) -> SmallVec<[Self; 2]> {
1148        use miden_assembly::ast::{Instruction, InvocationTarget};
1149
1150        use crate::Symbol;
1151
1152        let op = match ix {
1153            Instruction::Assert => Self::Assert,
1154            Instruction::AssertWithError(code) => Self::AssertWithError(unwrap_u32!(code)),
1155            Instruction::AssertEq => Self::AssertEq,
1156            Instruction::AssertEqWithError(code) => Self::AssertEqWithError(unwrap_u32!(code)),
1157            Instruction::AssertEqw => Self::AssertEqw,
1158            Instruction::AssertEqwWithError(code) => Self::AssertEqwWithError(unwrap_u32!(code)),
1159            Instruction::Assertz => Self::Assertz,
1160            Instruction::AssertzWithError(code) => Self::AssertzWithError(unwrap_u32!(code)),
1161            Instruction::Add => Self::Add,
1162            Instruction::AddImm(imm) => Self::AddImm(unwrap_imm!(imm)),
1163            Instruction::Sub => Self::Sub,
1164            Instruction::SubImm(imm) => Self::SubImm(unwrap_imm!(imm)),
1165            Instruction::Mul => Self::Mul,
1166            Instruction::MulImm(imm) => Self::MulImm(unwrap_imm!(imm)),
1167            Instruction::Div => Self::Div,
1168            Instruction::DivImm(imm) => Self::DivImm(unwrap_imm!(imm)),
1169            Instruction::Neg => Self::Neg,
1170            Instruction::Inv => Self::Inv,
1171            Instruction::Incr => Self::Incr,
1172            Instruction::ILog2 => Self::Ilog2,
1173            Instruction::Pow2 => Self::Pow2,
1174            Instruction::Exp => Self::Exp,
1175            Instruction::ExpImm(imm) => {
1176                Self::ExpImm(unwrap_imm!(imm).as_int().try_into().expect("invalid exponent"))
1177            }
1178            Instruction::ExpBitLength(imm) => Self::ExpBitLength(imm),
1179            Instruction::Not => Self::Not,
1180            Instruction::And => Self::And,
1181            Instruction::Or => Self::Or,
1182            Instruction::Xor => Self::Xor,
1183            Instruction::Eq => Self::Eq,
1184            Instruction::EqImm(imm) => Self::EqImm(unwrap_imm!(imm)),
1185            Instruction::Neq => Self::Neq,
1186            Instruction::NeqImm(imm) => Self::NeqImm(unwrap_imm!(imm)),
1187            Instruction::Eqw => Self::Eqw,
1188            Instruction::Lt => Self::Lt,
1189            Instruction::Lte => Self::Lte,
1190            Instruction::Gt => Self::Gt,
1191            Instruction::Gte => Self::Gte,
1192            Instruction::IsOdd => Self::IsOdd,
1193            Instruction::Hash => Self::Hash,
1194            Instruction::HMerge => Self::Hmerge,
1195            Instruction::HPerm => Self::Hperm,
1196            Instruction::MTreeGet => Self::MtreeGet,
1197            Instruction::MTreeSet => Self::MtreeSet,
1198            Instruction::MTreeMerge => Self::MtreeMerge,
1199            Instruction::MTreeVerify => Self::MtreeVerify,
1200            Instruction::MTreeVerifyWithError(code) => {
1201                Self::MtreeVerifyWithError(unwrap_u32!(code))
1202            }
1203            Instruction::Ext2Add => Self::Ext2add,
1204            Instruction::Ext2Sub => Self::Ext2sub,
1205            Instruction::Ext2Mul => Self::Ext2mul,
1206            Instruction::Ext2Div => Self::Ext2div,
1207            Instruction::Ext2Neg => Self::Ext2neg,
1208            Instruction::Ext2Inv => Self::Ext2inv,
1209            Instruction::FriExt2Fold4 => Self::FriExt2Fold4,
1210            Instruction::RCombBase => Self::RCombBase,
1211            Instruction::U32Test => Self::U32Test,
1212            Instruction::U32TestW => Self::U32Testw,
1213            Instruction::U32Assert => Self::U32Assert,
1214            Instruction::U32AssertWithError(code) => Self::U32AssertWithError(unwrap_u32!(code)),
1215            Instruction::U32Assert2 => Self::U32Assert2,
1216            Instruction::U32Assert2WithError(code) => Self::U32Assert2WithError(unwrap_u32!(code)),
1217            Instruction::U32AssertW => Self::U32Assertw,
1218            Instruction::U32AssertWWithError(code) => Self::U32AssertwWithError(unwrap_u32!(code)),
1219            Instruction::U32Split => Self::U32Split,
1220            Instruction::U32Cast => Self::U32Cast,
1221            Instruction::U32WrappingAdd => Self::U32WrappingAdd,
1222            Instruction::U32WrappingAddImm(imm) => Self::U32WrappingAddImm(unwrap_u32!(imm)),
1223            Instruction::U32OverflowingAdd => Self::U32OverflowingAdd,
1224            Instruction::U32OverflowingAddImm(imm) => Self::U32OverflowingAddImm(unwrap_u32!(imm)),
1225            Instruction::U32OverflowingAdd3 => Self::U32OverflowingAdd3,
1226            Instruction::U32WrappingAdd3 => Self::U32WrappingAdd3,
1227            Instruction::U32WrappingSub => Self::U32WrappingSub,
1228            Instruction::U32WrappingSubImm(imm) => Self::U32WrappingSubImm(unwrap_u32!(imm)),
1229            Instruction::U32OverflowingSub => Self::U32OverflowingSub,
1230            Instruction::U32OverflowingSubImm(imm) => Self::U32OverflowingSubImm(unwrap_u32!(imm)),
1231            Instruction::U32WrappingMul => Self::U32WrappingMul,
1232            Instruction::U32WrappingMulImm(imm) => Self::U32WrappingMulImm(unwrap_u32!(imm)),
1233            Instruction::U32OverflowingMul => Self::U32OverflowingMul,
1234            Instruction::U32OverflowingMulImm(imm) => Self::U32OverflowingMulImm(unwrap_u32!(imm)),
1235            Instruction::U32OverflowingMadd => Self::U32OverflowingMadd,
1236            Instruction::U32WrappingMadd => Self::U32WrappingMadd,
1237            Instruction::U32Div => Self::U32Div,
1238            Instruction::U32DivImm(imm) => Self::U32DivImm(unwrap_u32!(imm)),
1239            Instruction::U32Mod => Self::U32Mod,
1240            Instruction::U32ModImm(imm) => Self::U32ModImm(unwrap_u32!(imm)),
1241            Instruction::U32DivMod => Self::U32DivMod,
1242            Instruction::U32DivModImm(imm) => Self::U32DivModImm(unwrap_u32!(imm)),
1243            Instruction::U32And => Self::U32And,
1244            Instruction::U32Or => Self::U32Or,
1245            Instruction::U32Xor => Self::U32Xor,
1246            Instruction::U32Not => Self::U32Not,
1247            Instruction::U32Shr => Self::U32Shr,
1248            Instruction::U32ShrImm(imm) => Self::U32ShrImm(unwrap_u8!(imm) as u32),
1249            Instruction::U32Shl => Self::U32Shl,
1250            Instruction::U32ShlImm(imm) => Self::U32ShlImm(unwrap_u8!(imm) as u32),
1251            Instruction::U32Rotr => Self::U32Rotr,
1252            Instruction::U32RotrImm(imm) => Self::U32RotrImm(unwrap_u8!(imm) as u32),
1253            Instruction::U32Rotl => Self::U32Rotl,
1254            Instruction::U32RotlImm(imm) => Self::U32RotlImm(unwrap_u8!(imm) as u32),
1255            Instruction::U32Popcnt => Self::U32Popcnt,
1256            Instruction::U32Clz => Self::U32Clz,
1257            Instruction::U32Ctz => Self::U32Ctz,
1258            Instruction::U32Clo => Self::U32Clo,
1259            Instruction::U32Cto => Self::U32Cto,
1260            Instruction::U32Lt => Self::U32Lt,
1261            Instruction::U32Lte => Self::U32Lte,
1262            Instruction::U32Gt => Self::U32Gt,
1263            Instruction::U32Gte => Self::U32Gte,
1264            Instruction::U32Min => Self::U32Min,
1265            Instruction::U32Max => Self::U32Max,
1266            Instruction::Drop => Self::Drop,
1267            Instruction::DropW => Self::Dropw,
1268            Instruction::PadW => Self::Padw,
1269            Instruction::Dup0 => Self::Dup(0),
1270            Instruction::Dup1 => Self::Dup(1),
1271            Instruction::Dup2 => Self::Dup(2),
1272            Instruction::Dup3 => Self::Dup(3),
1273            Instruction::Dup4 => Self::Dup(4),
1274            Instruction::Dup5 => Self::Dup(5),
1275            Instruction::Dup6 => Self::Dup(6),
1276            Instruction::Dup7 => Self::Dup(7),
1277            Instruction::Dup8 => Self::Dup(8),
1278            Instruction::Dup9 => Self::Dup(9),
1279            Instruction::Dup10 => Self::Dup(10),
1280            Instruction::Dup11 => Self::Dup(11),
1281            Instruction::Dup12 => Self::Dup(12),
1282            Instruction::Dup13 => Self::Dup(13),
1283            Instruction::Dup14 => Self::Dup(14),
1284            Instruction::Dup15 => Self::Dup(15),
1285            Instruction::DupW0 => Self::Dupw(0),
1286            Instruction::DupW1 => Self::Dupw(1),
1287            Instruction::DupW2 => Self::Dupw(2),
1288            Instruction::DupW3 => Self::Dupw(3),
1289            Instruction::Swap1 => Self::Swap(1),
1290            Instruction::Swap2 => Self::Swap(2),
1291            Instruction::Swap3 => Self::Swap(3),
1292            Instruction::Swap4 => Self::Swap(4),
1293            Instruction::Swap5 => Self::Swap(5),
1294            Instruction::Swap6 => Self::Swap(6),
1295            Instruction::Swap7 => Self::Swap(7),
1296            Instruction::Swap8 => Self::Swap(8),
1297            Instruction::Swap9 => Self::Swap(9),
1298            Instruction::Swap10 => Self::Swap(10),
1299            Instruction::Swap11 => Self::Swap(11),
1300            Instruction::Swap12 => Self::Swap(12),
1301            Instruction::Swap13 => Self::Swap(13),
1302            Instruction::Swap14 => Self::Swap(14),
1303            Instruction::Swap15 => Self::Swap(15),
1304            Instruction::SwapW1 => Self::Swapw(1),
1305            Instruction::SwapW2 => Self::Swapw(2),
1306            Instruction::SwapW3 => Self::Swapw(3),
1307            Instruction::SwapDw => Self::Swapdw,
1308            Instruction::MovUp2 => Self::Movup(2),
1309            Instruction::MovUp3 => Self::Movup(3),
1310            Instruction::MovUp4 => Self::Movup(4),
1311            Instruction::MovUp5 => Self::Movup(5),
1312            Instruction::MovUp6 => Self::Movup(6),
1313            Instruction::MovUp7 => Self::Movup(7),
1314            Instruction::MovUp8 => Self::Movup(8),
1315            Instruction::MovUp9 => Self::Movup(9),
1316            Instruction::MovUp10 => Self::Movup(10),
1317            Instruction::MovUp11 => Self::Movup(11),
1318            Instruction::MovUp12 => Self::Movup(12),
1319            Instruction::MovUp13 => Self::Movup(13),
1320            Instruction::MovUp14 => Self::Movup(14),
1321            Instruction::MovUp15 => Self::Movup(15),
1322            Instruction::MovUpW2 => Self::Movupw(2),
1323            Instruction::MovUpW3 => Self::Movupw(3),
1324            Instruction::MovDn2 => Self::Movdn(2),
1325            Instruction::MovDn3 => Self::Movdn(3),
1326            Instruction::MovDn4 => Self::Movdn(4),
1327            Instruction::MovDn5 => Self::Movdn(5),
1328            Instruction::MovDn6 => Self::Movdn(6),
1329            Instruction::MovDn7 => Self::Movdn(7),
1330            Instruction::MovDn8 => Self::Movdn(8),
1331            Instruction::MovDn9 => Self::Movdn(9),
1332            Instruction::MovDn10 => Self::Movdn(10),
1333            Instruction::MovDn11 => Self::Movdn(11),
1334            Instruction::MovDn12 => Self::Movdn(12),
1335            Instruction::MovDn13 => Self::Movdn(13),
1336            Instruction::MovDn14 => Self::Movdn(14),
1337            Instruction::MovDn15 => Self::Movdn(15),
1338            Instruction::MovDnW2 => Self::Movdnw(2),
1339            Instruction::MovDnW3 => Self::Movdnw(3),
1340            Instruction::CSwap => Self::Cswap,
1341            Instruction::CSwapW => Self::Cswapw,
1342            Instruction::CDrop => Self::Cdrop,
1343            Instruction::CDropW => Self::Cdropw,
1344            Instruction::Push(elem) => Self::Push(unwrap_imm!(elem)),
1345            Instruction::PushU8(elem) => Self::PushU8(elem),
1346            Instruction::PushU16(elem) => Self::PushU16(elem),
1347            Instruction::PushU32(elem) => Self::PushU32(elem),
1348            Instruction::PushFelt(elem) => Self::Push(elem),
1349            Instruction::PushWord(word) => Self::Pushw(word),
1350            Instruction::PushU8List(u8s) => return u8s.into_iter().map(Self::PushU8).collect(),
1351            Instruction::PushU16List(u16s) => return u16s.into_iter().map(Self::PushU16).collect(),
1352            Instruction::PushU32List(u32s) => return u32s.into_iter().map(Self::PushU32).collect(),
1353            Instruction::PushFeltList(felts) => return felts.into_iter().map(Self::Push).collect(),
1354            Instruction::Locaddr(id) => Self::LocAddr(LocalId::from_u16(unwrap_u16!(id))),
1355            Instruction::LocStore(id) => Self::LocStore(LocalId::from_u16(unwrap_u16!(id))),
1356            Instruction::LocStoreW(id) => Self::LocStorew(LocalId::from_u16(unwrap_u16!(id))),
1357            Instruction::Clk => Self::Clk,
1358            Instruction::MemLoad => Self::MemLoad,
1359            Instruction::MemLoadImm(addr) => Self::MemLoadImm(unwrap_u32!(addr)),
1360            Instruction::MemLoadW => Self::MemLoadw,
1361            Instruction::MemLoadWImm(addr) => Self::MemLoadwImm(unwrap_u32!(addr)),
1362            Instruction::MemStore => Self::MemStore,
1363            Instruction::MemStoreImm(addr) => Self::MemStoreImm(unwrap_u32!(addr)),
1364            Instruction::MemStoreW => Self::MemStorew,
1365            Instruction::MemStoreWImm(addr) => Self::MemStorewImm(unwrap_u32!(addr)),
1366            Instruction::LocLoad(imm) => Self::LocLoad(LocalId::from_u16(unwrap_u16!(imm))),
1367            Instruction::LocLoadW(imm) => Self::LocLoadw(LocalId::from_u16(unwrap_u16!(imm))),
1368            Instruction::MemStream => Self::MemStream,
1369            Instruction::AdvPipe => Self::AdvPipe,
1370            Instruction::AdvPush(byte) => Self::AdvPush(unwrap_u8!(byte)),
1371            Instruction::AdvLoadW => Self::AdvLoadw,
1372            Instruction::AdvInject(AdviceInjectorNode::InsertMem) => Self::AdvInjectInsertMem,
1373            Instruction::AdvInject(AdviceInjectorNode::InsertHperm) => Self::AdvInjectInsertHperm,
1374            Instruction::AdvInject(AdviceInjectorNode::InsertHdword) => Self::AdvInjectInsertHdword,
1375            Instruction::AdvInject(AdviceInjectorNode::InsertHdwordImm { domain }) => {
1376                Self::AdvInjectInsertHdwordImm(unwrap_u8!(domain))
1377            }
1378            Instruction::AdvInject(AdviceInjectorNode::PushU64Div) => Self::AdvInjectPushU64Div,
1379            Instruction::AdvInject(AdviceInjectorNode::PushMtNode) => Self::AdvInjectPushMTreeNode,
1380            Instruction::AdvInject(AdviceInjectorNode::PushMapVal) => Self::AdvInjectPushMapVal,
1381            Instruction::AdvInject(AdviceInjectorNode::PushMapValImm { offset }) => {
1382                Self::AdvInjectPushMapValImm(unwrap_u8!(offset))
1383            }
1384            Instruction::AdvInject(AdviceInjectorNode::PushMapValN) => Self::AdvInjectPushMapValN,
1385            Instruction::AdvInject(AdviceInjectorNode::PushMapValNImm { offset }) => {
1386                Self::AdvInjectPushMapValNImm(unwrap_u8!(offset))
1387            }
1388            Instruction::AdvInject(AdviceInjectorNode::PushSignature { kind }) => {
1389                Self::AdvInjectPushSignature(kind)
1390            }
1391            Instruction::AdvInject(injector) => {
1392                unimplemented!("unsupported advice injector: {injector:?}")
1393            }
1394            ref ix @ (Instruction::Exec(ref target)
1395            | Instruction::SysCall(ref target)
1396            | Instruction::Call(ref target)
1397            | Instruction::ProcRef(ref target)) => {
1398                let id = match target {
1399                    InvocationTarget::AbsoluteProcedurePath { name, path } => {
1400                        let name: &str = name.as_ref();
1401                        let function = Ident::with_empty_span(Symbol::intern(name));
1402                        let module = Ident::with_empty_span(Symbol::intern(path.to_string()));
1403                        FunctionIdent { module, function }
1404                    }
1405                    InvocationTarget::ProcedurePath { name, module } => {
1406                        let name: &str = name.as_ref();
1407                        let function = Ident::with_empty_span(Symbol::intern(name));
1408                        let module = Ident::with_empty_span(Symbol::intern(module.as_str()));
1409                        FunctionIdent { module, function }
1410                    }
1411                    InvocationTarget::ProcedureName(name) => {
1412                        let name: &str = name.as_ref();
1413                        let function = Ident::with_empty_span(Symbol::intern(name));
1414                        FunctionIdent {
1415                            module: current_module,
1416                            function,
1417                        }
1418                    }
1419                    InvocationTarget::MastRoot(_root) => {
1420                        todo!("support for referencing mast roots is not yet implemented")
1421                    }
1422                };
1423                match ix {
1424                    Instruction::Exec(_) => Self::Exec(id),
1425                    Instruction::SysCall(_) => Self::Syscall(id),
1426                    Instruction::Call(_) => Self::Call(id),
1427                    Instruction::ProcRef(_) => Self::ProcRef(id),
1428                    _ => unreachable!(),
1429                }
1430            }
1431            Instruction::DynExec => Self::DynExec,
1432            Instruction::DynCall => Self::DynCall,
1433            Instruction::Caller => Self::Caller,
1434            Instruction::Sdepth => Self::Sdepth,
1435            Instruction::Breakpoint => Self::Breakpoint,
1436            Instruction::Emit(event) => Self::Emit(unwrap_u32!(event)),
1437            Instruction::Trace(event) => Self::Trace(unwrap_u32!(event)),
1438            Instruction::Debug(DebugOptions::StackAll) => Self::DebugStack,
1439            Instruction::Debug(DebugOptions::StackTop(n)) => Self::DebugStackN(unwrap_u8!(n)),
1440            Instruction::Debug(DebugOptions::MemAll) => Self::DebugMemory,
1441            Instruction::Debug(DebugOptions::MemInterval(start, end)) => {
1442                Self::DebugMemoryRange(unwrap_u32!(start), unwrap_u32!(end))
1443            }
1444            Instruction::Debug(DebugOptions::LocalAll) => Self::DebugFrame,
1445            Instruction::Debug(DebugOptions::LocalRangeFrom(start)) => {
1446                Self::DebugFrameAt(unwrap_u16!(start))
1447            }
1448            Instruction::Debug(DebugOptions::LocalInterval(start, end)) => {
1449                Self::DebugFrameRange(unwrap_u16!(start), unwrap_u16!(end))
1450            }
1451            Instruction::Nop => Self::Nop,
1452        };
1453        smallvec![op]
1454    }
1455
1456    pub fn into_masm(
1457        self,
1458        imports: &super::ModuleImportInfo,
1459        locals: &BTreeSet<FunctionIdent>,
1460    ) -> SmallVec<[miden_assembly::ast::Instruction; 2]> {
1461        use miden_assembly::{
1462            ast::{Instruction, InvocationTarget, ProcedureName},
1463            LibraryPath,
1464        };
1465        let inst = match self {
1466            Self::Padw => Instruction::PadW,
1467            Self::Push(v) => Instruction::PushFelt(v),
1468            Self::Push2([a, b]) => Instruction::PushFeltList(vec![a, b]),
1469            Self::Pushw(word) => Instruction::PushWord(word),
1470            Self::PushU8(v) => Instruction::PushU8(v),
1471            Self::PushU16(v) => Instruction::PushU16(v),
1472            Self::PushU32(v) => Instruction::PushU32(v),
1473            Self::Drop => Instruction::Drop,
1474            Self::Dropw => Instruction::DropW,
1475            Self::Dup(0) => Instruction::Dup0,
1476            Self::Dup(1) => Instruction::Dup1,
1477            Self::Dup(2) => Instruction::Dup2,
1478            Self::Dup(3) => Instruction::Dup3,
1479            Self::Dup(4) => Instruction::Dup4,
1480            Self::Dup(5) => Instruction::Dup5,
1481            Self::Dup(6) => Instruction::Dup6,
1482            Self::Dup(7) => Instruction::Dup7,
1483            Self::Dup(8) => Instruction::Dup8,
1484            Self::Dup(9) => Instruction::Dup9,
1485            Self::Dup(10) => Instruction::Dup10,
1486            Self::Dup(11) => Instruction::Dup11,
1487            Self::Dup(12) => Instruction::Dup12,
1488            Self::Dup(13) => Instruction::Dup13,
1489            Self::Dup(14) => Instruction::Dup14,
1490            Self::Dup(15) => Instruction::Dup15,
1491            Self::Dup(n) => {
1492                panic!("invalid dup instruction, valid index range is 0..=15, got {n}")
1493            }
1494            Self::Dupw(0) => Instruction::DupW0,
1495            Self::Dupw(1) => Instruction::DupW1,
1496            Self::Dupw(2) => Instruction::DupW2,
1497            Self::Dupw(3) => Instruction::DupW3,
1498            Self::Dupw(n) => {
1499                panic!("invalid dupw instruction, valid index range is 0..=3, got {n}")
1500            }
1501            Self::Swap(1) => Instruction::Swap1,
1502            Self::Swap(2) => Instruction::Swap2,
1503            Self::Swap(3) => Instruction::Swap3,
1504            Self::Swap(4) => Instruction::Swap4,
1505            Self::Swap(5) => Instruction::Swap5,
1506            Self::Swap(6) => Instruction::Swap6,
1507            Self::Swap(7) => Instruction::Swap7,
1508            Self::Swap(8) => Instruction::Swap8,
1509            Self::Swap(9) => Instruction::Swap9,
1510            Self::Swap(10) => Instruction::Swap10,
1511            Self::Swap(11) => Instruction::Swap11,
1512            Self::Swap(12) => Instruction::Swap12,
1513            Self::Swap(13) => Instruction::Swap13,
1514            Self::Swap(14) => Instruction::Swap14,
1515            Self::Swap(15) => Instruction::Swap15,
1516            Self::Swap(n) => {
1517                panic!("invalid swap instruction, valid index range is 1..=15, got {n}")
1518            }
1519            Self::Swapw(1) => Instruction::SwapW1,
1520            Self::Swapw(2) => Instruction::SwapW2,
1521            Self::Swapw(3) => Instruction::SwapW3,
1522            Self::Swapw(n) => {
1523                panic!("invalid swapw instruction, valid index range is 1..=3, got {n}")
1524            }
1525            Self::Swapdw => Instruction::SwapDw,
1526            Self::Movup(2) => Instruction::MovUp2,
1527            Self::Movup(3) => Instruction::MovUp3,
1528            Self::Movup(4) => Instruction::MovUp4,
1529            Self::Movup(5) => Instruction::MovUp5,
1530            Self::Movup(6) => Instruction::MovUp6,
1531            Self::Movup(7) => Instruction::MovUp7,
1532            Self::Movup(8) => Instruction::MovUp8,
1533            Self::Movup(9) => Instruction::MovUp9,
1534            Self::Movup(10) => Instruction::MovUp10,
1535            Self::Movup(11) => Instruction::MovUp11,
1536            Self::Movup(12) => Instruction::MovUp12,
1537            Self::Movup(13) => Instruction::MovUp13,
1538            Self::Movup(14) => Instruction::MovUp14,
1539            Self::Movup(15) => Instruction::MovUp15,
1540            Self::Movup(n) => {
1541                panic!("invalid movup instruction, valid index range is 2..=15, got {n}")
1542            }
1543            Self::Movupw(2) => Instruction::MovUpW2,
1544            Self::Movupw(3) => Instruction::MovUpW3,
1545            Self::Movupw(n) => {
1546                panic!("invalid movupw instruction, valid index range is 2..=3, got {n}")
1547            }
1548            Self::Movdn(2) => Instruction::MovDn2,
1549            Self::Movdn(3) => Instruction::MovDn3,
1550            Self::Movdn(4) => Instruction::MovDn4,
1551            Self::Movdn(5) => Instruction::MovDn5,
1552            Self::Movdn(6) => Instruction::MovDn6,
1553            Self::Movdn(7) => Instruction::MovDn7,
1554            Self::Movdn(8) => Instruction::MovDn8,
1555            Self::Movdn(9) => Instruction::MovDn9,
1556            Self::Movdn(10) => Instruction::MovDn10,
1557            Self::Movdn(11) => Instruction::MovDn11,
1558            Self::Movdn(12) => Instruction::MovDn12,
1559            Self::Movdn(13) => Instruction::MovDn13,
1560            Self::Movdn(14) => Instruction::MovDn14,
1561            Self::Movdn(15) => Instruction::MovDn15,
1562            Self::Movdn(n) => {
1563                panic!("invalid movdn instruction, valid index range is 2..=15, got {n}")
1564            }
1565            Self::Movdnw(2) => Instruction::MovDnW2,
1566            Self::Movdnw(3) => Instruction::MovDnW3,
1567            Self::Movdnw(n) => {
1568                panic!("invalid movdnw instruction, valid index range is 2..=3, got {n}")
1569            }
1570            Self::Cswap => Instruction::CSwap,
1571            Self::Cswapw => Instruction::CSwapW,
1572            Self::Cdrop => Instruction::CDrop,
1573            Self::Cdropw => Instruction::CDropW,
1574            Self::Assert => Instruction::Assert,
1575            Self::AssertWithError(code) => Instruction::AssertWithError(code.into()),
1576            Self::Assertz => Instruction::Assertz,
1577            Self::AssertzWithError(code) => Instruction::AssertzWithError(code.into()),
1578            Self::AssertEq => Instruction::AssertEq,
1579            Self::AssertEqWithError(code) => Instruction::AssertEqWithError(code.into()),
1580            Self::AssertEqw => Instruction::AssertEqw,
1581            Self::AssertEqwWithError(code) => Instruction::AssertEqwWithError(code.into()),
1582            Self::LocAddr(id) => Instruction::Locaddr(id.into()),
1583            Self::LocLoad(id) => Instruction::LocLoad(id.into()),
1584            Self::LocLoadw(id) => Instruction::LocLoadW(id.into()),
1585            Self::LocStore(id) => Instruction::LocStore(id.into()),
1586            Self::LocStorew(id) => Instruction::LocStoreW(id.into()),
1587            Self::MemLoad => Instruction::MemLoad,
1588            Self::MemLoadImm(addr) => Instruction::MemLoadImm(addr.into()),
1589            Self::MemLoadw => Instruction::MemLoadW,
1590            Self::MemLoadwImm(addr) => Instruction::MemLoadWImm(addr.into()),
1591            Self::MemStore => Instruction::MemStore,
1592            Self::MemStoreImm(addr) => Instruction::MemStoreImm(addr.into()),
1593            Self::MemStorew => Instruction::MemStoreW,
1594            Self::MemStorewImm(addr) => Instruction::MemStoreWImm(addr.into()),
1595            Self::MemStream => Instruction::MemStream,
1596            Self::AdvPipe => Instruction::AdvPipe,
1597            Self::AdvPush(n) => Instruction::AdvPush(n.into()),
1598            Self::AdvLoadw => Instruction::AdvLoadW,
1599            Self::AdvInjectPushU64Div => Instruction::AdvInject(AdviceInjectorNode::PushU64Div),
1600            Self::AdvInjectPushMTreeNode => Instruction::AdvInject(AdviceInjectorNode::PushMtNode),
1601            Self::AdvInjectPushMapVal => Instruction::AdvInject(AdviceInjectorNode::PushMapVal),
1602            Self::AdvInjectPushMapValImm(n) => {
1603                Instruction::AdvInject(AdviceInjectorNode::PushMapValImm { offset: n.into() })
1604            }
1605            Self::AdvInjectPushMapValN => Instruction::AdvInject(AdviceInjectorNode::PushMapValN),
1606            Self::AdvInjectPushMapValNImm(n) => {
1607                Instruction::AdvInject(AdviceInjectorNode::PushMapValNImm { offset: n.into() })
1608            }
1609            Self::AdvInjectInsertMem => Instruction::AdvInject(AdviceInjectorNode::InsertMem),
1610            Self::AdvInjectInsertHperm => Instruction::AdvInject(AdviceInjectorNode::InsertHperm),
1611            Self::AdvInjectInsertHdword => Instruction::AdvInject(AdviceInjectorNode::InsertHdword),
1612            Self::AdvInjectInsertHdwordImm(domain) => {
1613                Instruction::AdvInject(AdviceInjectorNode::InsertHdwordImm {
1614                    domain: domain.into(),
1615                })
1616            }
1617            Self::AdvInjectPushSignature(kind) => {
1618                Instruction::AdvInject(AdviceInjectorNode::PushSignature { kind })
1619            }
1620            Self::If(..) | Self::While(_) | Self::Repeat(..) => {
1621                panic!("control flow instructions are meant to be handled specially by the caller")
1622            }
1623            op @ (Self::Exec(ref callee)
1624            | Self::Call(ref callee)
1625            | Self::Syscall(ref callee)
1626            | Self::ProcRef(ref callee)) => {
1627                let target = if locals.contains(callee) {
1628                    let callee = ProcedureName::new_unchecked(super::utils::translate_ident(
1629                        callee.function,
1630                    ));
1631                    InvocationTarget::ProcedureName(callee)
1632                } else if let Some(alias) = imports.alias(&callee.module) {
1633                    let alias = super::utils::translate_ident(alias);
1634                    let name = ProcedureName::new_unchecked(super::utils::translate_ident(
1635                        callee.function,
1636                    ));
1637                    InvocationTarget::ProcedurePath {
1638                        name,
1639                        module: alias,
1640                    }
1641                } else {
1642                    let name = ProcedureName::new_unchecked(super::utils::translate_ident(
1643                        callee.function,
1644                    ));
1645                    let path =
1646                        LibraryPath::new(callee.module.as_str()).expect("invalid procedure path");
1647                    InvocationTarget::AbsoluteProcedurePath { name, path }
1648                };
1649                match op {
1650                    Self::Exec(_) => Instruction::Exec(target),
1651                    Self::Call(_) => Instruction::Call(target),
1652                    Self::Syscall(_) => Instruction::SysCall(target),
1653                    Self::ProcRef(_) => Instruction::ProcRef(target),
1654                    _ => unreachable!(),
1655                }
1656            }
1657            Self::DynExec => Instruction::DynExec,
1658            Self::DynCall => Instruction::DynCall,
1659            Self::Add => Instruction::Add,
1660            Self::AddImm(imm) => Instruction::AddImm(imm.into()),
1661            Self::Sub => Instruction::Sub,
1662            Self::SubImm(imm) => Instruction::SubImm(imm.into()),
1663            Self::Mul => Instruction::Mul,
1664            Self::MulImm(imm) => Instruction::MulImm(imm.into()),
1665            Self::Div => Instruction::Div,
1666            Self::DivImm(imm) => Instruction::DivImm(imm.into()),
1667            Self::Neg => Instruction::Neg,
1668            Self::Inv => Instruction::Inv,
1669            Self::Incr => Instruction::Incr,
1670            Self::Ilog2 => Instruction::ILog2,
1671            Self::Pow2 => Instruction::Pow2,
1672            Self::Exp => Instruction::Exp,
1673            Self::ExpImm(imm) => Instruction::ExpImm(Felt::new(imm as u64).into()),
1674            Self::ExpBitLength(imm) => Instruction::ExpBitLength(imm),
1675            Self::Not => Instruction::Not,
1676            Self::And => Instruction::And,
1677            Self::AndImm(imm) => {
1678                return smallvec![Instruction::PushU8(imm as u8), Instruction::And]
1679            }
1680            Self::Or => Instruction::Or,
1681            Self::OrImm(imm) => return smallvec![Instruction::PushU8(imm as u8), Instruction::Or],
1682            Self::Xor => Instruction::Xor,
1683            Self::XorImm(imm) => {
1684                return smallvec![Instruction::PushU8(imm as u8), Instruction::Xor]
1685            }
1686            Self::Eq => Instruction::Eq,
1687            Self::EqImm(imm) => Instruction::EqImm(imm.into()),
1688            Self::Neq => Instruction::Neq,
1689            Self::NeqImm(imm) => Instruction::NeqImm(imm.into()),
1690            Self::Gt => Instruction::Gt,
1691            Self::GtImm(imm) => return smallvec![Instruction::PushFelt(imm), Instruction::Gt],
1692            Self::Gte => Instruction::Gte,
1693            Self::GteImm(imm) => return smallvec![Instruction::PushFelt(imm), Instruction::Gte],
1694            Self::Lt => Instruction::Lt,
1695            Self::LtImm(imm) => return smallvec![Instruction::PushFelt(imm), Instruction::Lt],
1696            Self::Lte => Instruction::Lte,
1697            Self::LteImm(imm) => return smallvec![Instruction::PushFelt(imm), Instruction::Lte],
1698            Self::IsOdd => Instruction::IsOdd,
1699            Self::Eqw => Instruction::Eqw,
1700            Self::Ext2add => Instruction::Ext2Add,
1701            Self::Ext2sub => Instruction::Ext2Sub,
1702            Self::Ext2mul => Instruction::Ext2Mul,
1703            Self::Ext2div => Instruction::Ext2Div,
1704            Self::Ext2neg => Instruction::Ext2Neg,
1705            Self::Ext2inv => Instruction::Ext2Inv,
1706            Self::Clk => Instruction::Clk,
1707            Self::Caller => Instruction::Caller,
1708            Self::Sdepth => Instruction::Sdepth,
1709            Self::Hash => Instruction::Hash,
1710            Self::Hperm => Instruction::HPerm,
1711            Self::Hmerge => Instruction::HMerge,
1712            Self::MtreeGet => Instruction::MTreeGet,
1713            Self::MtreeSet => Instruction::MTreeSet,
1714            Self::MtreeMerge => Instruction::MTreeMerge,
1715            Self::MtreeVerify => Instruction::MTreeVerify,
1716            Self::MtreeVerifyWithError(code) => Instruction::MTreeVerifyWithError(code.into()),
1717            Self::FriExt2Fold4 => Instruction::FriExt2Fold4,
1718            Self::RCombBase => Instruction::RCombBase,
1719            Self::U32Test => Instruction::U32Test,
1720            Self::U32Testw => Instruction::U32TestW,
1721            Self::U32Assert => Instruction::U32Assert,
1722            Self::U32AssertWithError(code) => Instruction::U32AssertWithError(code.into()),
1723            Self::U32Assert2 => Instruction::U32Assert2,
1724            Self::U32Assert2WithError(code) => Instruction::U32Assert2WithError(code.into()),
1725            Self::U32Assertw => Instruction::U32AssertW,
1726            Self::U32AssertwWithError(code) => Instruction::U32AssertWWithError(code.into()),
1727            Self::U32Cast => Instruction::U32Cast,
1728            Self::U32Split => Instruction::U32Split,
1729            Self::U32OverflowingAdd => Instruction::U32OverflowingAdd,
1730            Self::U32OverflowingAddImm(imm) => Instruction::U32OverflowingAddImm(imm.into()),
1731            Self::U32WrappingAdd => Instruction::U32WrappingAdd,
1732            Self::U32WrappingAddImm(imm) => Instruction::U32WrappingAddImm(imm.into()),
1733            Self::U32OverflowingAdd3 => Instruction::U32OverflowingAdd3,
1734            Self::U32WrappingAdd3 => Instruction::U32WrappingAdd3,
1735            Self::U32OverflowingSub => Instruction::U32OverflowingSub,
1736            Self::U32OverflowingSubImm(imm) => Instruction::U32OverflowingSubImm(imm.into()),
1737            Self::U32WrappingSub => Instruction::U32WrappingSub,
1738            Self::U32WrappingSubImm(imm) => Instruction::U32WrappingSubImm(imm.into()),
1739            Self::U32OverflowingMul => Instruction::U32OverflowingMul,
1740            Self::U32OverflowingMulImm(imm) => Instruction::U32OverflowingMulImm(imm.into()),
1741            Self::U32WrappingMul => Instruction::U32WrappingMul,
1742            Self::U32WrappingMulImm(imm) => Instruction::U32WrappingMulImm(imm.into()),
1743            Self::U32OverflowingMadd => Instruction::U32OverflowingMadd,
1744            Self::U32WrappingMadd => Instruction::U32WrappingMadd,
1745            Self::U32Div => Instruction::U32Div,
1746            Self::U32DivImm(imm) => Instruction::U32DivImm(imm.into()),
1747            Self::U32Mod => Instruction::U32Mod,
1748            Self::U32ModImm(imm) => Instruction::U32ModImm(imm.into()),
1749            Self::U32DivMod => Instruction::U32DivMod,
1750            Self::U32DivModImm(imm) => Instruction::U32DivModImm(imm.into()),
1751            Self::U32And => Instruction::U32And,
1752            Self::U32Or => Instruction::U32Or,
1753            Self::U32Xor => Instruction::U32Xor,
1754            Self::U32Not => Instruction::U32Not,
1755            Self::U32Shl => Instruction::U32Shl,
1756            Self::U32ShlImm(imm) => {
1757                let shift = u8::try_from(imm).expect("invalid shift");
1758                Instruction::U32ShlImm(shift.into())
1759            }
1760            Self::U32Shr => Instruction::U32Shr,
1761            Self::U32ShrImm(imm) => {
1762                let shift = u8::try_from(imm).expect("invalid shift");
1763                Instruction::U32ShrImm(shift.into())
1764            }
1765            Self::U32Rotl => Instruction::U32Rotl,
1766            Self::U32RotlImm(imm) => {
1767                let rotate = u8::try_from(imm).expect("invalid rotation");
1768                Instruction::U32RotlImm(rotate.into())
1769            }
1770            Self::U32Rotr => Instruction::U32Rotr,
1771            Self::U32RotrImm(imm) => {
1772                let rotate = u8::try_from(imm).expect("invalid rotation");
1773                Instruction::U32RotrImm(rotate.into())
1774            }
1775            Self::U32Popcnt => Instruction::U32Popcnt,
1776            Self::U32Clz => Instruction::U32Clz,
1777            Self::U32Ctz => Instruction::U32Ctz,
1778            Self::U32Clo => Instruction::U32Clo,
1779            Self::U32Cto => Instruction::U32Cto,
1780            Self::U32Lt => Instruction::U32Lt,
1781            Self::U32LtImm(imm) => return smallvec![Instruction::PushU32(imm), Instruction::U32Lt],
1782            Self::U32Lte => Instruction::U32Lte,
1783            Self::U32LteImm(imm) => {
1784                return smallvec![Instruction::PushU32(imm), Instruction::U32Lte]
1785            }
1786            Self::U32Gt => Instruction::U32Gt,
1787            Self::U32GtImm(imm) => return smallvec![Instruction::PushU32(imm), Instruction::U32Gt],
1788            Self::U32Gte => Instruction::U32Gte,
1789            Self::U32GteImm(imm) => {
1790                return smallvec![Instruction::PushU32(imm), Instruction::U32Gte];
1791            }
1792            Self::U32Min => Instruction::U32Min,
1793            Self::U32MinImm(imm) => {
1794                return smallvec![Instruction::PushU32(imm), Instruction::U32Min];
1795            }
1796            Self::U32Max => Instruction::U32Max,
1797            Self::U32MaxImm(imm) => {
1798                return smallvec![Instruction::PushU32(imm), Instruction::U32Max];
1799            }
1800            Self::Breakpoint => Instruction::Breakpoint,
1801            Self::DebugStack => Instruction::Debug(DebugOptions::StackAll),
1802            Self::DebugStackN(n) => Instruction::Debug(DebugOptions::StackTop(n.into())),
1803            Self::DebugMemory => Instruction::Debug(DebugOptions::MemAll),
1804            Self::DebugMemoryAt(start) => {
1805                Instruction::Debug(DebugOptions::MemInterval(start.into(), u32::MAX.into()))
1806            }
1807            Self::DebugMemoryRange(start, end) => {
1808                Instruction::Debug(DebugOptions::MemInterval(start.into(), end.into()))
1809            }
1810            Self::DebugFrame => Instruction::Debug(DebugOptions::LocalAll),
1811            Self::DebugFrameAt(start) => {
1812                Instruction::Debug(DebugOptions::LocalRangeFrom(start.into()))
1813            }
1814            Self::DebugFrameRange(start, end) => {
1815                Instruction::Debug(DebugOptions::LocalInterval(start.into(), end.into()))
1816            }
1817            Self::Emit(ev) => Instruction::Emit(ev.into()),
1818            Self::Trace(ev) => Instruction::Trace(ev.into()),
1819            Self::Nop => Instruction::Nop,
1820        };
1821        smallvec![inst]
1822    }
1823}
1824
1825impl fmt::Display for MasmOp {
1827    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1828        match self {
1829            Self::Padw => f.write_str("padw"),
1830            Self::Push(_)
1831            | Self::Push2(_)
1832            | Self::Pushw(_)
1833            | Self::PushU8(_)
1834            | Self::PushU16(_)
1835            | Self::PushU32(_) => f.write_str("push"),
1836            Self::Drop => f.write_str("drop"),
1837            Self::Dropw => f.write_str("dropw"),
1838            Self::Dup(_) => f.write_str("dup"),
1839            Self::Dupw(_) => f.write_str("dupw"),
1840            Self::Swap(_) => f.write_str("swap"),
1841            Self::Swapw(_) => f.write_str("swapw"),
1842            Self::Swapdw => f.write_str("swapdw"),
1843            Self::Movup(_) => f.write_str("movup"),
1844            Self::Movupw(_) => f.write_str("movupw"),
1845            Self::Movdn(_) => f.write_str("movdn"),
1846            Self::Movdnw(_) => f.write_str("movdnw"),
1847            Self::Cswap => f.write_str("cswap"),
1848            Self::Cswapw => f.write_str("cswapw"),
1849            Self::Cdrop => f.write_str("cdrop"),
1850            Self::Cdropw => f.write_str("cdropw"),
1851            Self::Assert => f.write_str("assert"),
1852            Self::AssertWithError(code) => write!(f, "assert.err={code}"),
1853            Self::Assertz => f.write_str("assertz"),
1854            Self::AssertzWithError(code) => write!(f, "assertz.err={code}"),
1855            Self::AssertEq => f.write_str("assert_eq"),
1856            Self::AssertEqWithError(code) => write!(f, "assert_eq.err={code}"),
1857            Self::AssertEqw => f.write_str("assert_eqw"),
1858            Self::AssertEqwWithError(code) => write!(f, "assert_eqw.err={code}"),
1859            Self::LocAddr(_) => f.write_str("locaddr"),
1860            Self::LocLoad(_) => f.write_str("loc_load"),
1861            Self::LocLoadw(_) => f.write_str("loc_loadw"),
1862            Self::LocStore(_) => f.write_str("loc_store"),
1863            Self::LocStorew(_) => f.write_str("loc_storew"),
1864            Self::MemLoad | Self::MemLoadImm(_) => f.write_str("mem_load"),
1865            Self::MemLoadw | Self::MemLoadwImm(_) => f.write_str("mem_loadw"),
1866            Self::MemStore | Self::MemStoreImm(_) => f.write_str("mem_store"),
1867            Self::MemStorew | Self::MemStorewImm(_) => f.write_str("mem_storew"),
1868            Self::MemStream => f.write_str("mem_stream"),
1869            Self::AdvPipe => f.write_str("adv_pipe"),
1870            Self::AdvPush(_) => f.write_str("adv_push"),
1871            Self::AdvLoadw => f.write_str("adv_loadw"),
1872            Self::AdvInjectPushU64Div => f.write_str("adv.push_u64div"),
1873            Self::AdvInjectPushMTreeNode => f.write_str("adv.push_mtnode"),
1874            Self::AdvInjectPushMapVal | Self::AdvInjectPushMapValImm(_) => {
1875                f.write_str("adv.push_mapval")
1876            }
1877            Self::AdvInjectPushMapValN | Self::AdvInjectPushMapValNImm(_) => {
1878                f.write_str("adv.push_mapvaln")
1879            }
1880            Self::AdvInjectInsertMem => f.write_str("adv.insert_mem"),
1881            Self::AdvInjectInsertHperm => f.write_str("adv.insert_hperm"),
1882            Self::AdvInjectInsertHdword | Self::AdvInjectInsertHdwordImm(_) => {
1883                f.write_str("adv.insert_hdword")
1884            }
1885            Self::AdvInjectPushSignature(kind) => write!(f, "adv.push_sig.{kind}"),
1886            Self::If(..) => f.write_str("if.true"),
1887            Self::While(_) => f.write_str("while.true"),
1888            Self::Repeat(..) => f.write_str("repeat"),
1889            Self::Exec(_) => f.write_str("exec"),
1890            Self::Syscall(_) => f.write_str("syscall"),
1891            Self::Call(_) => f.write_str("call"),
1892            Self::DynExec => f.write_str("dynexec"),
1893            Self::DynCall => f.write_str("dyncall"),
1894            Self::ProcRef(_) => f.write_str("procref"),
1895            Self::Add | Self::AddImm(_) => f.write_str("add"),
1896            Self::Sub | Self::SubImm(_) => f.write_str("sub"),
1897            Self::Mul | Self::MulImm(_) => f.write_str("mul"),
1898            Self::Div | Self::DivImm(_) => f.write_str("div"),
1899            Self::Neg => f.write_str("neg"),
1900            Self::Inv => f.write_str("inv"),
1901            Self::Incr => f.write_str("add.1"),
1902            Self::Ilog2 => f.write_str("ilog2"),
1903            Self::Pow2 => f.write_str("pow2"),
1904            Self::Exp => f.write_str("exp"),
1905            Self::ExpImm(imm) => write!(f, "exp.{imm}"),
1906            Self::ExpBitLength(imm) => write!(f, "exp.u{imm}"),
1907            Self::Not => f.write_str("not"),
1908            Self::And | Self::AndImm(_) => f.write_str("and"),
1909            Self::Or | Self::OrImm(_) => f.write_str("or"),
1910            Self::Xor | Self::XorImm(_) => f.write_str("xor"),
1911            Self::Eq | Self::EqImm(_) => f.write_str("eq"),
1912            Self::Neq | Self::NeqImm(_) => f.write_str("neq"),
1913            Self::Gt | Self::GtImm(_) => f.write_str("gt"),
1914            Self::Gte | Self::GteImm(_) => f.write_str("gte"),
1915            Self::Lt | Self::LtImm(_) => f.write_str("lt"),
1916            Self::Lte | Self::LteImm(_) => f.write_str("lte"),
1917            Self::IsOdd => f.write_str("is_odd"),
1918            Self::Eqw => f.write_str("eqw"),
1919            Self::Ext2add => f.write_str("ext2add"),
1920            Self::Ext2sub => f.write_str("ext2sub"),
1921            Self::Ext2mul => f.write_str("ext2mul"),
1922            Self::Ext2div => f.write_str("ext2div"),
1923            Self::Ext2neg => f.write_str("ext2neg"),
1924            Self::Ext2inv => f.write_str("ext2inv"),
1925            Self::Clk => f.write_str("clk"),
1926            Self::Caller => f.write_str("caller"),
1927            Self::Sdepth => f.write_str("sdepth"),
1928            Self::Hash => f.write_str("hash"),
1929            Self::Hperm => f.write_str("hperm"),
1930            Self::Hmerge => f.write_str("hmerge"),
1931            Self::MtreeGet => f.write_str("mtree_get"),
1932            Self::MtreeSet => f.write_str("mtree_set"),
1933            Self::MtreeMerge => f.write_str("mtree_merge"),
1934            Self::MtreeVerify => f.write_str("mtree_verify"),
1935            Self::MtreeVerifyWithError(code) => write!(f, "mtree_verify.err={code}"),
1936            Self::FriExt2Fold4 => f.write_str("fri_ext2fold4"),
1937            Self::RCombBase => f.write_str("rcomb_base"),
1938            Self::U32Test => f.write_str("u32test"),
1939            Self::U32Testw => f.write_str("u32testw"),
1940            Self::U32Assert => f.write_str("u32assert"),
1941            Self::U32AssertWithError(code) => write!(f, "u32assert.err={code}"),
1942            Self::U32Assert2 => f.write_str("u32assert2"),
1943            Self::U32Assert2WithError(code) => write!(f, "u32assert2.err={code}"),
1944            Self::U32Assertw => f.write_str("u32assertw"),
1945            Self::U32AssertwWithError(code) => write!(f, "u32assertw.err={code}"),
1946            Self::U32Cast => f.write_str("u32cast"),
1947            Self::U32Split => f.write_str("u32split"),
1948            Self::U32OverflowingAdd | Self::U32OverflowingAddImm(_) => {
1949                f.write_str("u32overflowing_add")
1950            }
1951            Self::U32WrappingAdd | Self::U32WrappingAddImm(_) => f.write_str("u32wrapping_add"),
1952            Self::U32OverflowingAdd3 => f.write_str("u32overflowing_add3"),
1953            Self::U32WrappingAdd3 => f.write_str("u32wrapping_add3"),
1954            Self::U32OverflowingSub | Self::U32OverflowingSubImm(_) => {
1955                f.write_str("u32overflowing_sub")
1956            }
1957            Self::U32WrappingSub | Self::U32WrappingSubImm(_) => f.write_str("u32wrapping_sub"),
1958            Self::U32OverflowingMul | Self::U32OverflowingMulImm(_) => {
1959                f.write_str("u32overflowing_mul")
1960            }
1961            Self::U32WrappingMul | Self::U32WrappingMulImm(_) => f.write_str("u32wrapping_mul"),
1962            Self::U32OverflowingMadd => f.write_str("u32overflowing_madd"),
1963            Self::U32WrappingMadd => f.write_str("u32wrapping_madd"),
1964            Self::U32Div | Self::U32DivImm(_) => f.write_str("u32div"),
1965            Self::U32Mod | Self::U32ModImm(_) => f.write_str("u32mod"),
1966            Self::U32DivMod | Self::U32DivModImm(_) => f.write_str("u32divmod"),
1967            Self::U32And => f.write_str("u32and"),
1968            Self::U32Or => f.write_str("u32or"),
1969            Self::U32Xor => f.write_str("u32xor"),
1970            Self::U32Not => f.write_str("u32not"),
1971            Self::U32Shl | Self::U32ShlImm(_) => f.write_str("u32shl"),
1972            Self::U32Shr | Self::U32ShrImm(_) => f.write_str("u32shr"),
1973            Self::U32Rotl | Self::U32RotlImm(_) => f.write_str("u32rotl"),
1974            Self::U32Rotr | Self::U32RotrImm(_) => f.write_str("u32rotr"),
1975            Self::U32Popcnt => f.write_str("u32popcnt"),
1976            Self::U32Clz => f.write_str("u32clz"),
1977            Self::U32Ctz => f.write_str("u32ctz"),
1978            Self::U32Clo => f.write_str("u32clo"),
1979            Self::U32Cto => f.write_str("u32cto"),
1980            Self::U32Lt | Self::U32LtImm(_) => f.write_str("u32lt"),
1981            Self::U32Lte | Self::U32LteImm(_) => f.write_str("u32lte"),
1982            Self::U32Gt | Self::U32GtImm(_) => f.write_str("u32gt"),
1983            Self::U32Gte | Self::U32GteImm(_) => f.write_str("u32gte"),
1984            Self::U32Min | Self::U32MinImm(_) => f.write_str("u32min"),
1985            Self::U32Max | Self::U32MaxImm(_) => f.write_str("u32max"),
1986            Self::Breakpoint => f.write_str("breakpoint"),
1987            Self::DebugStack | Self::DebugStackN(_) => f.write_str("debug.stack"),
1988            Self::DebugMemory | Self::DebugMemoryAt(_) | Self::DebugMemoryRange(..) => {
1989                f.write_str("debug.mem")
1990            }
1991            Self::DebugFrame | Self::DebugFrameAt(_) | Self::DebugFrameRange(..) => {
1992                f.write_str("debug.local")
1993            }
1994            Self::Emit(_) => f.write_str("emit"),
1995            Self::Trace(_) => f.write_str("trace"),
1996            Self::Nop => f.write_str("nop"),
1997        }
1998    }
1999}