/
githubmirror
/
sway
Обзор
Документация
Войти
/
githubmirror
/
sway
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
sway-ast/src/expr/op_code.rs
394 строки
13 KB
Igor Rončević
Implement dynamic storage opcodes in the compiler (#7595)
16 апр 2026, 13:15
Не верифицирован
16 апр 2026, 13:15
fbb524c
Код
Авторство
О чём код?
use crate::priv_prelude::*; macro_rules! define_op_code ( ($ty_name:ident, $s:literal) => ( #[derive(Clone, Debug, Serialize)] pub struct $ty_name { span: Span, } impl Spanned for $ty_name { fn span(&self) -> Span { self.span.clone() } } ); ); macro_rules! op_code_ty ( (reg) => { Ident }; (imm) => { AsmImmediate }; ); macro_rules! push_register_arg_idents ( ($vec_name:ident, ()) => {}; ($vec_name:ident, ($arg_name_head:ident: reg, $($arg_name:ident: $arg_ty:tt,)*)) => { $vec_name.push($arg_name_head.clone()); push_register_arg_idents!($vec_name, ($($arg_name: $arg_ty,)*)) }; ($vec_name:ident, ($arg_name_head:ident: imm, $($arg_name:ident: $arg_ty:tt,)*)) => { let _ = $arg_name_head; push_register_arg_idents!($vec_name, ($($arg_name: $arg_ty,)*)) }; ); macro_rules! push_immediate_idents ( ($vec_name:ident, ()) => {}; ($vec_name:ident, ($arg_name_head:ident: reg, $($arg_name:ident: $arg_ty:tt,)*)) => { let _ = $arg_name_head; push_immediate_idents!($vec_name, ($($arg_name: $arg_ty,)*)) }; ($vec_name:ident, ($arg_name_head:ident: imm, $($arg_name:ident: $arg_ty:tt,)*)) => { $vec_name.push(Ident::new($arg_name_head.span())); push_immediate_idents!($vec_name, ($($arg_name: $arg_ty,)*)) }; ); macro_rules! ignore_remaining ( () => {}; ($arg_name_head:ident: $arg_ty_head:tt, $($arg_name:ident: $arg_ty:tt,)*) => {{ let _ = $arg_name_head; ignore_remaining!($($arg_name: $arg_ty,)*); }}; ); macro_rules! immediate_ident_opt ( () => { None }; ($arg_name_head:ident: reg, $($arg_name:ident: $arg_ty:tt,)*) => {{ let _ = $arg_name_head; immediate_ident_opt!($($arg_name: $arg_ty,)*) }}; ($arg_name_head:ident: imm, $($arg_name:ident: $arg_ty:tt,)*) => {{ ignore_remaining!($($arg_name: $arg_ty,)*); Some(Ident::new($arg_name_head.span())) }}; ); macro_rules! get_span ( ($start:expr, ()) => { $start }; ($start:expr, ($arg_name:ident,)) => { Span::join($start, &$arg_name.span()) }; ($start:expr, ($arg_name_head:ident, $($arg_name:ident,)*)) => {{ let _ = $arg_name_head; get_span!($start, ($($arg_name,)*)) }}; ); /// A specific instruction. pub trait Inst { /// The instruction's literal in source code. const LIT: &'static str; /// Arguments to the instruction. type Args; fn instruction(ident: Ident, args: Self::Args) -> Instruction; } macro_rules! define_op_codes ( ($(($op_name:ident, $ty_name:ident, $s:literal, ($($arg_name:ident: $arg_ty:tt),*)),)*) => { $( define_op_code!($ty_name, $s); impl Inst for $ty_name { const LIT: &'static str = $s; type Args = ($(op_code_ty!($arg_ty),)*); fn instruction(ident: Ident, ($($arg_name,)*): Self::Args) -> Instruction { Instruction::$op_name { token: $ty_name { span: ident.span().clone() }, $($arg_name,)* } } } )* #[derive(Clone, Debug, Serialize)] pub enum Instruction { $($op_name { token: $ty_name, $($arg_name: op_code_ty!($arg_ty),)* },)* } impl Instruction { pub fn op_code_ident(&self) -> Ident { match self { $(Instruction::$op_name { token, .. } => { Ident::new(token.span()) },)* } } pub fn op_code_as_str(&self) -> &'static str { match self { $(Instruction::$op_name { .. } => { $s },)* } } #[allow(clippy::vec_init_then_push)] pub fn register_arg_idents(&self) -> Vec<Ident> { match self { $(Instruction::$op_name { $($arg_name,)* .. } => { #[allow(unused_mut)] let mut ret = Vec::new(); push_register_arg_idents!(ret, ($($arg_name: $arg_ty,)*)); ret },)* } } pub fn immediate_ident_opt(&self) -> Option<Ident> { match self { $(Instruction::$op_name { $($arg_name,)* .. } => { immediate_ident_opt!($($arg_name: $arg_ty,)*) },)* } } #[allow(clippy::vec_init_then_push)] pub fn immediate_idents(&self) -> Vec<Ident> { match self { $(Instruction::$op_name { $($arg_name,)* .. } => { #[allow(unused_mut)] let mut ret = Vec::new(); push_immediate_idents!(ret, ($($arg_name: $arg_ty,)*)); ret },)* } } } impl Spanned for Instruction { fn span(&self) -> Span { match self { $(Instruction::$op_name { token, $($arg_name,)* } => { get_span!(token.span(), ($($arg_name,)*)) },)* } } } }; ); define_op_codes!( /* Arithmetic/Logic (ALU) Instructions */ (Add, AddOpcode, "add", (ret: reg, lhs: reg, rhs: reg)), (Addi, AddiOpcode, "addi", (ret: reg, lhs: reg, rhs: imm)), (And, AndOpcode, "and", (ret: reg, lhs: reg, rhs: reg)), (Andi, AndiOpcode, "andi", (ret: reg, lhs: reg, rhs: imm)), (Div, DivOpcode, "div", (ret: reg, lhs: reg, rhs: reg)), (Divi, DiviOpcode, "divi", (ret: reg, lhs: reg, rhs: imm)), (Eq, EqOpcode, "eq", (ret: reg, lhs: reg, rhs: reg)), (Exp, ExpOpcode, "exp", (ret: reg, base: reg, power: reg)), (Expi, ExpiOpcode, "expi", (ret: reg, base: reg, power: imm)), (Gt, GtOpcode, "gt", (ret: reg, lhs: reg, rhs: reg)), (Lt, LtOpcode, "lt", (ret: reg, lhs: reg, rhs: reg)), (Mlog, MlogOpcode, "mlog", (ret: reg, arg: reg, base: reg)), (Mod, ModOpcode, "mod", (ret: reg, lhs: reg, rhs: reg)), (Modi, ModiOpcode, "modi", (ret: reg, lhs: reg, rhs: imm)), (Move, MoveOpcode, "move", (ret: reg, from: reg)), (Movi, MoviOpcode, "movi", (ret: reg, arg: imm)), (Mroo, MrooOpcode, "mroo", (ret: reg, arg: reg, root: reg)), (Mul, MulOpcode, "mul", (ret: reg, lhs: reg, rhs: reg)), (Muli, MuliOpcode, "muli", (ret: reg, lhs: reg, rhs: imm)), (Noop, NoopOpcode, "noop", ()), (Not, NotOpcode, "not", (ret: reg, arg: reg)), (Or, OrOpcode, "or", (ret: reg, lhs: reg, rhs: reg)), (Ori, OriOpcode, "ori", (ret: reg, lhs: reg, rhs: imm)), (Sll, SllOpcode, "sll", (ret: reg, lhs: reg, rhs: reg)), (Slli, SlliOpcode, "slli", (ret: reg, lhs: reg, rhs: imm)), (Srl, SrlOpcode, "srl", (ret: reg, lhs: reg, rhs: reg)), (Srli, SrliOpcode, "srli", (ret: reg, lhs: reg, rhs: imm)), (Sub, SubOpcode, "sub", (ret: reg, lhs: reg, rhs: reg)), (Subi, SubiOpcode, "subi", (ret: reg, lhs: reg, rhs: imm)), (Wqcm, WqcmOpcode, "wqcm", (ret: reg, lhs: reg, rhs: reg, op_mode: imm)), (Wqop, WqopOpcode, "wqop", (ret: reg, lhs: reg, rhs: reg, op_mode: imm)), (Wqml, WqmlOpcode, "wqml", (ret: reg, lhs: reg, rhs: reg, indirect: imm)), (Wqdv, WqdvOpcode, "wqdv", (ret: reg, lhs: reg, rhs: reg, indirect: imm)), (Wqmd, WqmdOpcode, "wqmd", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)), (Wqam, WqamOpcode, "wqam", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)), (Wqmm, WqmmOpcode, "wqmm", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)), (Xor, XorOpcode, "xor", (ret: reg, lhs: reg, rhs: reg)), (Xori, XoriOpcode, "xori", (ret: reg, lhs: reg, rhs: imm)), /* Control Flow Instructions */ (Jmp, JmpOpcode, "jmp", (offset: reg)), (Ji, JiOpcode, "ji", (offset: imm)), (Jne, JneOpcode, "jne", (lhs: reg, rhs: reg, offset: reg)), (Jnei, JneiOpcode, "jnei", (lhs: reg, rhs: reg, offset: imm)), (Jnzi, JnziOpcode, "jnzi", (arg: reg, offset: imm)), (Jmpb, JmpbOpcode, "jmpb", (offset_reg: reg, offset: imm)), (Jmpf, JmpfOpcode, "jmpf", (offset_reg: reg, offset: imm)), (Jnzb, JnzbOpcode, "jnzb", (arg: reg, offset_reg: reg, offset: imm)), (Jnzf, JnzfOpcode, "jnzf", (arg: reg, offset_reg: reg, offset: imm)), (Jneb, JnebOpcode, "jneb", (lhs: reg, rhs: reg, offset_reg: reg, offset: imm)), (Jnef, JnefOpcode, "jnef", (lhs: reg, rhs: reg, offset_reg: reg, offset: imm)), (Jal, JalOpcode, "jal", (addr: reg, offset_reg: reg, offset: imm)), (Ret, RetOpcode, "ret", (value: reg)), /* Memory Instructions */ (Aloc, AlocOpcode, "aloc", (size: reg)), (Cfei, CfeiOpcode, "cfei", (size: imm)), (Cfsi, CfsiOpcode, "cfsi", (size: imm)), (Cfe, CfeOpcode, "cfe", (size: reg)), (Cfs, CfsOpcode, "cfs", (size: reg)), (Lb, LbOpcode, "lb", (ret: reg, addr: reg, offset: imm)), (Lw, LwOpcode, "lw", (ret: reg, addr: reg, offset: imm)), (Mcl, MclOpcode, "mcl", (addr: reg, size: reg)), (Mcli, McliOpcode, "mcli", (addr: reg, size: imm)), ( Mcp, McpOpcode, "mcp", (dst_addr: reg, src_addr: reg, size: reg) ), ( Mcpi, McpiOpcode, "mcpi", (dst_addr: reg, src_addr: reg, size: imm) ), ( Meq, MeqOpcode, "meq", (ret: reg, lhs_addr: reg, rhs_addr: reg, size: reg) ), (Sb, SbOpcode, "sb", (addr: reg, value: reg, offset: imm)), (Sw, SwOpcode, "sw", (addr: reg, value: reg, offset: imm)), /* Contract Instructions */ (Bal, BalOpcode, "bal", (ret: reg, asset: reg, contract: reg)), (Bhei, BheiOpcode, "bhei", (ret: reg)), (Bhsh, BhshOpcode, "bhsh", (addr: reg, height: reg)), (Burn, BurnOpcode, "burn", (coins: reg, sub_id: reg)), ( Call, CallOpcode, "call", (args_addr: reg, coins: reg, asset: reg, gas: reg) ), (Cb, CbOpcode, "cb", (addr: reg)), ( Ccp, CcpOpcode, "ccp", (dst_addr: reg, contract: reg, src_addr: reg, size: reg) ), (Croo, CrooOpcode, "croo", (addr: reg, contract: reg)), (Csiz, CsizOpcode, "csiz", (ret: reg, contract: reg)), (Bsiz, BsizOpcode, "bsiz", (ret: reg, contract: reg)), (Ldc, LdcOpcode, "ldc", (contract: reg, addr: reg, size: reg, mode: imm)), (Bldd, BlddOpcode, "bldd", (dst_ptr: reg, addr: reg, offset: reg, len: reg)), ( Log, LogOpcode, "log", (reg_a: reg, reg_b: reg, reg_c: reg, reg_d: reg) ), ( Logd, LogdOpcode, "logd", (reg_a: reg, reg_b: reg, addr: reg, size: reg) ), (Mint, MintOpcode, "mint", (coins: reg, sub_id: reg)), (Retd, RetdOpcode, "retd", (addr: reg, size: reg)), (Rvrt, RvrtOpcode, "rvrt", (value: reg)), ( Smo, SmoOpcode, "smo", (addr: reg, len: reg, output: reg, coins: reg) ), (Scwq, ScwqOpcode, "scwq", (addr: reg, is_set: reg, len: reg)), (Sclr, SclrOpcode, "sclr", (addr: reg, len: reg)), ( Srw, SrwOpcode, "srw", (ret: reg, is_set: reg, state_addr: reg, offset: imm) ), ( Srwq, SrwqOpcode, "srwq", (addr: reg, is_set: reg, state_addr: reg, count: reg) ), ( Srdd, SrddOpcode, "srdd", (addr: reg, state_addr: reg, offset: reg, len: reg) ), ( Srdi, SrdiOpcode, "srdi", (addr: reg, state_addr: reg, offset: reg, len: imm) ), ( Sww, SwwOpcode, "sww", (state_addr: reg, is_set: reg, value: reg) ), ( Swwq, SwwqOpcode, "swwq", (state_addr: reg, is_set: reg, addr: reg, count: reg) ), (Swrd, SwrdOpcode, "swrd", (state_addr: reg, addr: reg, len: reg)), (Swri, SwriOpcode, "swri", (state_addr: reg, addr: reg, len: imm)), ( Supd, SupdOpcode, "supd", (state_addr: reg, addr: reg, offset: reg, len: reg) ), ( Supi, SupiOpcode, "supi", (state_addr: reg, addr: reg, offset: reg, len: imm) ), ( Spld, SpldOpcode, "spld", (dest_len: reg, state_addr: reg) ), (Time, TimeOpcode, "time", (ret: reg, height: reg)), (Tr, TrOpcode, "tr", (contract: reg, coins: reg, asset: reg)), ( Tro, TroOpcode, "tro", (addr: reg, output: reg, coins: reg, asset: reg) ), /* Cryptographic Instructions */ (Eck1, Eck1Opcode, "eck1", (addr: reg, sig: reg, hash: reg)), (Ecr1, Ecr1Opcode, "ecr1", (addr: reg, sig: reg, hash: reg)), (Ed19, Ed19Opcode, "ed19", (addr: reg, sig: reg, hash: reg, len: reg)), (K256, K256Opcode, "k256", (addr: reg, data: reg, size: reg)), (S256, S256Opcode, "s256", (addr: reg, data: reg, size: reg)), (ECOP, ECOPOpcode, "ecop", (dst_addr: reg, curve: reg, operation: reg, src_addr: reg)), (EPAR, EPAROpcode, "epar", (ret: reg, curve: reg, groups_of_points: reg, addr: reg)), /* Other Instructions */ (Ecal, EcalOpcode, "ecal", (reg_a: reg, reg_b: reg, reg_c: reg, reg_d: reg)), (Flag, FlagOpcode, "flag", (value: reg)), (Gm, GmOpcode, "gm", (ret: reg, op: imm)), ( Gtf, GtfOpcode, "gtf", (ret: reg, index: reg, tx_field_id: imm) ), /* Non-VM Instructions */ (Blob, BlobOpcode, "blob", (size: imm)), );