sway_ast/expr/
op_code.rs

1use crate::priv_prelude::*;
2
3macro_rules! define_op_code (
4    ($ty_name:ident, $s:literal) => (
5        #[derive(Clone, Debug, Serialize)]
6        pub struct $ty_name {
7            span: Span,
8        }
9
10        impl Spanned for $ty_name {
11            fn span(&self) -> Span {
12                self.span.clone()
13            }
14        }
15    );
16);
17
18macro_rules! op_code_ty (
19    (reg) => { Ident };
20    (imm) => { AsmImmediate };
21);
22
23macro_rules! push_register_arg_idents (
24    ($vec_name:ident, ()) => {};
25    ($vec_name:ident, ($arg_name_head:ident: reg, $($arg_name:ident: $arg_ty:tt,)*)) => {
26        $vec_name.push($arg_name_head.clone());
27        push_register_arg_idents!($vec_name, ($($arg_name: $arg_ty,)*))
28    };
29    ($vec_name:ident, ($arg_name_head:ident: imm, $($arg_name:ident: $arg_ty:tt,)*)) => {
30        let _ = $arg_name_head;
31        push_register_arg_idents!($vec_name, ($($arg_name: $arg_ty,)*))
32    };
33);
34
35macro_rules! push_immediate_idents (
36    ($vec_name:ident, ()) => {};
37    ($vec_name:ident, ($arg_name_head:ident: reg, $($arg_name:ident: $arg_ty:tt,)*)) => {
38        let _ = $arg_name_head;
39        push_immediate_idents!($vec_name, ($($arg_name: $arg_ty,)*))
40    };
41    ($vec_name:ident, ($arg_name_head:ident: imm, $($arg_name:ident: $arg_ty:tt,)*)) => {
42        $vec_name.push(Ident::new($arg_name_head.span()));
43        push_immediate_idents!($vec_name, ($($arg_name: $arg_ty,)*))
44    };
45);
46
47macro_rules! ignore_remaining (
48    () => {};
49    ($arg_name_head:ident: $arg_ty_head:tt, $($arg_name:ident: $arg_ty:tt,)*) => {{
50        let _ = $arg_name_head;
51        ignore_remaining!($($arg_name: $arg_ty,)*);
52    }};
53);
54
55macro_rules! immediate_ident_opt (
56    () => {
57        None
58    };
59    ($arg_name_head:ident: reg, $($arg_name:ident: $arg_ty:tt,)*) => {{
60        let _ = $arg_name_head;
61        immediate_ident_opt!($($arg_name: $arg_ty,)*)
62    }};
63    ($arg_name_head:ident: imm, $($arg_name:ident: $arg_ty:tt,)*) => {{
64        ignore_remaining!($($arg_name: $arg_ty,)*);
65        Some(Ident::new($arg_name_head.span()))
66    }};
67);
68
69macro_rules! get_span (
70    ($start:expr, ()) => { $start };
71    ($start:expr, ($arg_name:ident,)) => {
72        Span::join($start, &$arg_name.span())
73    };
74    ($start:expr, ($arg_name_head:ident, $($arg_name:ident,)*)) => {{
75        let _ = $arg_name_head;
76        get_span!($start, ($($arg_name,)*))
77    }};
78);
79
80/// A specific instruction.
81pub trait Inst {
82    /// The instruction's literal in source code.
83    const LIT: &'static str;
84
85    /// Arguments to the instruction.
86    type Args;
87
88    fn instruction(ident: Ident, args: Self::Args) -> Instruction;
89}
90
91macro_rules! define_op_codes (
92    ($(($op_name:ident, $ty_name:ident, $s:literal, ($($arg_name:ident: $arg_ty:tt),*)),)*) => {
93        $(
94            define_op_code!($ty_name, $s);
95
96            impl Inst for $ty_name {
97                const LIT: &'static str = $s;
98                type Args = ($(op_code_ty!($arg_ty),)*);
99
100                fn instruction(ident: Ident, ($($arg_name,)*): Self::Args) -> Instruction {
101                    Instruction::$op_name {
102                        token: $ty_name { span: ident.span().clone() },
103                        $($arg_name,)*
104                    }
105                }
106            }
107        )*
108
109        #[derive(Clone, Debug, Serialize)]
110        pub enum Instruction {
111            $($op_name {
112                token: $ty_name,
113                $($arg_name: op_code_ty!($arg_ty),)*
114            },)*
115        }
116
117        impl Instruction {
118            pub fn op_code_ident(&self) -> Ident {
119                match self {
120                    $(Instruction::$op_name { token, .. } => {
121                        Ident::new(token.span())
122                    },)*
123                }
124            }
125
126            pub fn op_code_as_str(&self) -> &'static str {
127                match self {
128                    $(Instruction::$op_name { .. } => {
129                        $s
130                    },)*
131                }
132            }
133
134            #[allow(clippy::vec_init_then_push)]
135            pub fn register_arg_idents(&self) -> Vec<Ident> {
136                match self {
137                    $(Instruction::$op_name { $($arg_name,)* .. } => {
138                        #[allow(unused_mut)]
139                        let mut ret = Vec::new();
140                        push_register_arg_idents!(ret, ($($arg_name: $arg_ty,)*));
141                        ret
142                    },)*
143                }
144            }
145
146            pub fn immediate_ident_opt(&self) -> Option<Ident> {
147                match self {
148                    $(Instruction::$op_name { $($arg_name,)* .. } => {
149                        immediate_ident_opt!($($arg_name: $arg_ty,)*)
150                    },)*
151                }
152            }
153
154            #[allow(clippy::vec_init_then_push)]
155            pub fn immediate_idents(&self) -> Vec<Ident> {
156                match self {
157                    $(Instruction::$op_name { $($arg_name,)* .. } => {
158                        #[allow(unused_mut)]
159                        let mut ret = Vec::new();
160                        push_immediate_idents!(ret, ($($arg_name: $arg_ty,)*));
161                        ret
162                    },)*
163                }
164            }
165
166        }
167
168        impl Spanned for Instruction {
169            fn span(&self) -> Span {
170                match self {
171                    $(Instruction::$op_name { token, $($arg_name,)* } => {
172                        get_span!(token.span(), ($($arg_name,)*))
173                    },)*
174                }
175            }
176        }
177    };
178);
179
180define_op_codes!(
181    /* Arithmetic/Logic (ALU) Instructions */
182    (Add, AddOpcode, "add", (ret: reg, lhs: reg, rhs: reg)),
183    (Addi, AddiOpcode, "addi", (ret: reg, lhs: reg, rhs: imm)),
184    (And, AndOpcode, "and", (ret: reg, lhs: reg, rhs: reg)),
185    (Andi, AndiOpcode, "andi", (ret: reg, lhs: reg, rhs: imm)),
186    (Div, DivOpcode, "div", (ret: reg, lhs: reg, rhs: reg)),
187    (Divi, DiviOpcode, "divi", (ret: reg, lhs: reg, rhs: imm)),
188    (Eq, EqOpcode, "eq", (ret: reg, lhs: reg, rhs: reg)),
189    (Exp, ExpOpcode, "exp", (ret: reg, base: reg, power: reg)),
190    (Expi, ExpiOpcode, "expi", (ret: reg, base: reg, power: imm)),
191    (Gt, GtOpcode, "gt", (ret: reg, lhs: reg, rhs: reg)),
192    (Lt, LtOpcode, "lt", (ret: reg, lhs: reg, rhs: reg)),
193    (Mlog, MlogOpcode, "mlog", (ret: reg, arg: reg, base: reg)),
194    (Mod, ModOpcode, "mod", (ret: reg, lhs: reg, rhs: reg)),
195    (Modi, ModiOpcode, "modi", (ret: reg, lhs: reg, rhs: imm)),
196    (Move, MoveOpcode, "move", (ret: reg, from: reg)),
197    (Movi, MoviOpcode, "movi", (ret: reg, arg: imm)),
198    (Mroo, MrooOpcode, "mroo", (ret: reg, arg: reg, root: reg)),
199    (Mul, MulOpcode, "mul", (ret: reg, lhs: reg, rhs: reg)),
200    (Muli, MuliOpcode, "muli", (ret: reg, lhs: reg, rhs: imm)),
201    (Noop, NoopOpcode, "noop", ()),
202    (Not, NotOpcode, "not", (ret: reg, arg: reg)),
203    (Or, OrOpcode, "or", (ret: reg, lhs: reg, rhs: reg)),
204    (Ori, OriOpcode, "ori", (ret: reg, lhs: reg, rhs: imm)),
205    (Sll, SllOpcode, "sll", (ret: reg, lhs: reg, rhs: reg)),
206    (Slli, SlliOpcode, "slli", (ret: reg, lhs: reg, rhs: imm)),
207    (Srl, SrlOpcode, "srl", (ret: reg, lhs: reg, rhs: reg)),
208    (Srli, SrliOpcode, "srli", (ret: reg, lhs: reg, rhs: imm)),
209    (Sub, SubOpcode, "sub", (ret: reg, lhs: reg, rhs: reg)),
210    (Subi, SubiOpcode, "subi", (ret: reg, lhs: reg, rhs: imm)),
211    (Wqcm, WqcmOpcode, "wqcm", (ret: reg, lhs: reg, rhs: reg, op_mode: imm)),
212    (Wqop, WqopOpcode, "wqop", (ret: reg, lhs: reg, rhs: reg, op_mode: imm)),
213    (Wqml, WqmlOpcode, "wqml", (ret: reg, lhs: reg, rhs: reg, indirect: imm)),
214    (Wqdv, WqdvOpcode, "wqdv", (ret: reg, lhs: reg, rhs: reg, indirect: imm)),
215    (Wqmd, WqmdOpcode, "wqmd", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)),
216    (Wqam, WqamOpcode, "wqam", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)),
217    (Wqmm, WqmmOpcode, "wqmm", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)),
218    (Xor, XorOpcode, "xor", (ret: reg, lhs: reg, rhs: reg)),
219    (Xori, XoriOpcode, "xori", (ret: reg, lhs: reg, rhs: imm)),
220    /* Control Flow Instructions */
221    (Jmp, JmpOpcode, "jmp", (offset: reg)),
222    (Ji, JiOpcode, "ji", (offset: imm)),
223    (Jne, JneOpcode, "jne", (lhs: reg, rhs: reg, offset: reg)),
224    (Jnei, JneiOpcode, "jnei", (lhs: reg, rhs: reg, offset: imm)),
225    (Jnzi, JnziOpcode, "jnzi", (arg: reg, offset: imm)),
226    (Jmpb, JmpbOpcode, "jmpb", (offset_reg: reg, offset: imm)),
227    (Jmpf, JmpfOpcode, "jmpf", (offset_reg: reg, offset: imm)),
228    (Jnzb, JnzbOpcode, "jnzb", (arg: reg, offset_reg: reg, offset: imm)),
229    (Jnzf, JnzfOpcode, "jnzf", (arg: reg, offset_reg: reg, offset: imm)),
230    (Jneb, JnebOpcode, "jneb", (lhs: reg, rhs: reg, offset_reg: reg, offset: imm)),
231    (Jnef, JnefOpcode, "jnef", (lhs: reg, rhs: reg, offset_reg: reg, offset: imm)),
232    (Jal, JalOpcode, "jal", (addr: reg, offset_reg: reg, offset: imm)),
233    (Ret, RetOpcode, "ret", (value: reg)),
234    /* Memory Instructions */
235    (Aloc, AlocOpcode, "aloc", (size: reg)),
236    (Cfei, CfeiOpcode, "cfei", (size: imm)),
237    (Cfsi, CfsiOpcode, "cfsi", (size: imm)),
238    (Cfe, CfeOpcode, "cfe", (size: reg)),
239    (Cfs, CfsOpcode, "cfs", (size: reg)),
240    (Lb, LbOpcode, "lb", (ret: reg, addr: reg, offset: imm)),
241    (Lw, LwOpcode, "lw", (ret: reg, addr: reg, offset: imm)),
242    (Mcl, MclOpcode, "mcl", (addr: reg, size: reg)),
243    (Mcli, McliOpcode, "mcli", (addr: reg, size: imm)),
244    (
245        Mcp,
246        McpOpcode,
247        "mcp",
248        (dst_addr: reg, src_addr: reg, size: reg)
249    ),
250    (
251        Mcpi,
252        McpiOpcode,
253        "mcpi",
254        (dst_addr: reg, src_addr: reg, size: imm)
255    ),
256    (
257        Meq,
258        MeqOpcode,
259        "meq",
260        (ret: reg, lhs_addr: reg, rhs_addr: reg, size: reg)
261    ),
262    (Sb, SbOpcode, "sb", (addr: reg, value: reg, offset: imm)),
263    (Sw, SwOpcode, "sw", (addr: reg, value: reg, offset: imm)),
264    /* Contract Instructions */
265    (Bal, BalOpcode, "bal", (ret: reg, asset: reg, contract: reg)),
266    (Bhei, BheiOpcode, "bhei", (ret: reg)),
267    (Bhsh, BhshOpcode, "bhsh", (addr: reg, height: reg)),
268    (Burn, BurnOpcode, "burn", (coins: reg, sub_id: reg)),
269    (
270        Call,
271        CallOpcode,
272        "call",
273        (args_addr: reg, coins: reg, asset: reg, gas: reg)
274    ),
275    (Cb, CbOpcode, "cb", (addr: reg)),
276    (
277        Ccp,
278        CcpOpcode,
279        "ccp",
280        (dst_addr: reg, contract: reg, src_addr: reg, size: reg)
281    ),
282    (Croo, CrooOpcode, "croo", (addr: reg, contract: reg)),
283    (Csiz, CsizOpcode, "csiz", (ret: reg, contract: reg)),
284    (Bsiz, BsizOpcode, "bsiz", (ret: reg, contract: reg)),
285    (Ldc, LdcOpcode, "ldc", (contract: reg, addr: reg, size: reg, mode: imm)),
286    (Bldd, BlddOpcode, "bldd", (dst_ptr: reg, addr: reg, offset: reg, len: reg)),
287    (
288        Log,
289        LogOpcode,
290        "log",
291        (reg_a: reg, reg_b: reg, reg_c: reg, reg_d: reg)
292    ),
293    (
294        Logd,
295        LogdOpcode,
296        "logd",
297        (reg_a: reg, reg_b: reg, addr: reg, size: reg)
298    ),
299    (Mint, MintOpcode, "mint", (coins: reg, sub_id: reg)),
300    (Retd, RetdOpcode, "retd", (addr: reg, size: reg)),
301    (Rvrt, RvrtOpcode, "rvrt", (value: reg)),
302    (
303        Smo,
304        SmoOpcode,
305        "smo",
306        (addr: reg, len: reg, output: reg, coins: reg)
307    ),
308    (Scwq, ScwqOpcode, "scwq", (addr: reg, is_set: reg, len: reg)),
309    (
310        Srw,
311        SrwOpcode,
312        "srw",
313        (ret: reg, is_set: reg, state_addr: reg)
314    ),
315    (
316        Srwq,
317        SrwqOpcode,
318        "srwq",
319        (addr: reg, is_set: reg, state_addr: reg, count: reg)
320    ),
321    (
322        Sww,
323        SwwOpcode,
324        "sww",
325        (state_addr: reg, is_set: reg, value: reg)
326    ),
327    (
328        Swwq,
329        SwwqOpcode,
330        "swwq",
331        (state_addr: reg, is_set: reg, addr: reg, count: reg)
332    ),
333    (Time, TimeOpcode, "time", (ret: reg, height: reg)),
334    (Tr, TrOpcode, "tr", (contract: reg, coins: reg, asset: reg)),
335    (
336        Tro,
337        TroOpcode,
338        "tro",
339        (addr: reg, output: reg, coins: reg, asset: reg)
340    ),
341    /* Cryptographic Instructions */
342    (Eck1, Eck1Opcode, "eck1", (addr: reg, sig: reg, hash: reg)),
343    (Ecr1, Ecr1Opcode, "ecr1", (addr: reg, sig: reg, hash: reg)),
344    (Ed19, Ed19Opcode, "ed19", (addr: reg, sig: reg, hash: reg, len: reg)),
345    (K256, K256Opcode, "k256", (addr: reg, data: reg, size: reg)),
346    (S256, S256Opcode, "s256", (addr: reg, data: reg, size: reg)),
347    (ECOP, ECOPOpcode, "ecop", (dst_addr: reg, curve: reg, operation: reg, src_addr: reg)),
348    (EPAR, EPAROpcode, "epar", (ret: reg, curve: reg, groups_of_points: reg, addr: reg)),
349    /* Other Instructions */
350    (Ecal, EcalOpcode, "ecal", (reg_a: reg, reg_b: reg, reg_c: reg, reg_d: reg)),
351    (Flag, FlagOpcode, "flag", (value: reg)),
352    (Gm, GmOpcode, "gm", (ret: reg, op: imm)),
353    (
354        Gtf,
355        GtfOpcode,
356        "gtf",
357        (ret: reg, index: reg, tx_field_id: imm)
358    ),
359    /* Non-VM Instructions */
360    (Blob, BlobOpcode, "blob", (size: imm)),
361);