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}