504 lines
14 KiB
Rust
504 lines
14 KiB
Rust
use std::convert::TryFrom;
|
|
|
|
use parity_wasm::elements::Instruction;
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Clone, Copy)]
|
|
pub enum Load {
|
|
I32,
|
|
I64,
|
|
F32,
|
|
F64,
|
|
I32_I8,
|
|
I32_U8,
|
|
I32_I16,
|
|
I32_U16,
|
|
I64_I8,
|
|
I64_U8,
|
|
I64_I16,
|
|
I64_U16,
|
|
I64_I32,
|
|
I64_U32,
|
|
}
|
|
|
|
impl Load {
|
|
pub fn as_name(self) -> &'static str {
|
|
match self {
|
|
Self::I32 => "i32",
|
|
Self::I64 => "i64",
|
|
Self::F32 => "f32",
|
|
Self::F64 => "f64",
|
|
Self::I32_I8 => "i32_i8",
|
|
Self::I32_U8 => "i32_u8",
|
|
Self::I32_I16 => "i32_i16",
|
|
Self::I32_U16 => "i32_u16",
|
|
Self::I64_I8 => "i64_i8",
|
|
Self::I64_U8 => "i64_u8",
|
|
Self::I64_I16 => "i64_i16",
|
|
Self::I64_U16 => "i64_u16",
|
|
Self::I64_I32 => "i64_i32",
|
|
Self::I64_U32 => "i64_u32",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&Instruction> for Load {
|
|
type Error = ();
|
|
|
|
fn try_from(inst: &Instruction) -> Result<Self, Self::Error> {
|
|
let result = match inst {
|
|
Instruction::I32Load(_, _) => Self::I32,
|
|
Instruction::I64Load(_, _) => Self::I64,
|
|
Instruction::F32Load(_, _) => Self::F32,
|
|
Instruction::F64Load(_, _) => Self::F64,
|
|
Instruction::I32Load8S(_, _) => Self::I32_I8,
|
|
Instruction::I32Load8U(_, _) => Self::I32_U8,
|
|
Instruction::I32Load16S(_, _) => Self::I32_I16,
|
|
Instruction::I32Load16U(_, _) => Self::I32_U16,
|
|
Instruction::I64Load8S(_, _) => Self::I64_I8,
|
|
Instruction::I64Load8U(_, _) => Self::I64_U8,
|
|
Instruction::I64Load16S(_, _) => Self::I64_I16,
|
|
Instruction::I64Load16U(_, _) => Self::I64_U16,
|
|
Instruction::I64Load32S(_, _) => Self::I64_I32,
|
|
Instruction::I64Load32U(_, _) => Self::I64_U32,
|
|
_ => return Err(()),
|
|
};
|
|
|
|
Ok(result)
|
|
}
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Clone, Copy)]
|
|
pub enum Store {
|
|
I32,
|
|
I64,
|
|
F32,
|
|
F64,
|
|
I32_N8,
|
|
I32_N16,
|
|
I64_N8,
|
|
I64_N16,
|
|
I64_N32,
|
|
}
|
|
|
|
impl Store {
|
|
pub fn as_name(self) -> &'static str {
|
|
match self {
|
|
Self::I32 => "i32",
|
|
Self::I64 => "i64",
|
|
Self::F32 => "f32",
|
|
Self::F64 => "f64",
|
|
Self::I32_N8 => "i32_n8",
|
|
Self::I32_N16 => "i32_n16",
|
|
Self::I64_N8 => "i64_n8",
|
|
Self::I64_N16 => "i64_n16",
|
|
Self::I64_N32 => "i64_n32",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&Instruction> for Store {
|
|
type Error = ();
|
|
|
|
fn try_from(inst: &Instruction) -> Result<Self, Self::Error> {
|
|
let result = match inst {
|
|
Instruction::I32Store(_, _) => Self::I32,
|
|
Instruction::I64Store(_, _) => Self::I64,
|
|
Instruction::F32Store(_, _) => Self::F32,
|
|
Instruction::F64Store(_, _) => Self::F64,
|
|
Instruction::I32Store8(_, _) => Self::I32_N8,
|
|
Instruction::I32Store16(_, _) => Self::I32_N16,
|
|
Instruction::I64Store8(_, _) => Self::I64_N8,
|
|
Instruction::I64Store16(_, _) => Self::I64_N16,
|
|
Instruction::I64Store32(_, _) => Self::I64_N32,
|
|
_ => return Err(()),
|
|
};
|
|
|
|
Ok(result)
|
|
}
|
|
}
|
|
|
|
// Order of mnemonics is:
|
|
// operation_result_parameter
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Clone, Copy)]
|
|
pub enum UnOp {
|
|
Eqz_I32,
|
|
Eqz_I64,
|
|
Clz_I32,
|
|
Ctz_I32,
|
|
Popcnt_I32,
|
|
Clz_I64,
|
|
Ctz_I64,
|
|
Popcnt_I64,
|
|
Abs_FN,
|
|
Neg_FN,
|
|
Ceil_FN,
|
|
Floor_FN,
|
|
Trunc_FN,
|
|
Nearest_FN,
|
|
Sqrt_FN,
|
|
Wrap_I32_I64,
|
|
Trunc_I32_F32,
|
|
Trunc_U32_F32,
|
|
Trunc_I32_F64,
|
|
Trunc_U32_F64,
|
|
Extend_I64_I32,
|
|
Extend_U64_I32,
|
|
Trunc_I64_F32,
|
|
Trunc_U64_F32,
|
|
Trunc_I64_F64,
|
|
Trunc_U64_F64,
|
|
Convert_F32_I32,
|
|
Convert_F32_U32,
|
|
Convert_F32_I64,
|
|
Convert_F32_U64,
|
|
Demote_F32_F64,
|
|
Convert_F64_I32,
|
|
Convert_F64_U32,
|
|
Convert_F64_I64,
|
|
Convert_F64_U64,
|
|
Promote_F64_F32,
|
|
Reinterpret_I32_F32,
|
|
Reinterpret_I64_F64,
|
|
Reinterpret_F32_I32,
|
|
Reinterpret_F64_I64,
|
|
}
|
|
|
|
impl UnOp {
|
|
pub fn as_operator(self) -> Option<&'static str> {
|
|
let op = match self {
|
|
Self::Neg_FN => "-",
|
|
_ => return None,
|
|
};
|
|
|
|
Some(op)
|
|
}
|
|
|
|
pub fn as_name(self) -> (&'static str, &'static str) {
|
|
match self {
|
|
Self::Eqz_I32 => ("eqz", "i32"),
|
|
Self::Eqz_I64 => ("eqz", "i64"),
|
|
Self::Clz_I32 => ("clz", "i32"),
|
|
Self::Ctz_I32 => ("ctz", "i32"),
|
|
Self::Popcnt_I32 => ("popcnt", "i32"),
|
|
Self::Clz_I64 => ("clz", "i64"),
|
|
Self::Ctz_I64 => ("ctz", "i64"),
|
|
Self::Popcnt_I64 => ("popcnt", "i64"),
|
|
Self::Abs_FN => ("math", "abs"),
|
|
Self::Neg_FN => ("neg", "num"),
|
|
Self::Ceil_FN => ("math", "ceil"),
|
|
Self::Floor_FN => ("math", "floor"),
|
|
Self::Trunc_FN => ("trunc", "num"),
|
|
Self::Nearest_FN => ("nearest", "num"),
|
|
Self::Sqrt_FN => ("math", "sqrt"),
|
|
Self::Wrap_I32_I64 => ("wrap", "i32_i64"),
|
|
Self::Trunc_I32_F32 => ("trunc", "i32_f32"),
|
|
Self::Trunc_U32_F32 => ("trunc", "u32_f32"),
|
|
Self::Trunc_I32_F64 => ("trunc", "i32_f64"),
|
|
Self::Trunc_U32_F64 => ("trunc", "u32_f64"),
|
|
Self::Extend_I64_I32 => ("extend", "i64_i32"),
|
|
Self::Extend_U64_I32 => ("extend", "u64_i32"),
|
|
Self::Trunc_I64_F32 => ("trunc", "i64_f32"),
|
|
Self::Trunc_U64_F32 => ("trunc", "u64_f32"),
|
|
Self::Trunc_I64_F64 => ("trunc", "i64_f64"),
|
|
Self::Trunc_U64_F64 => ("trunc", "u64_f64"),
|
|
Self::Convert_F32_I32 => ("convert", "f32_i32"),
|
|
Self::Convert_F32_U32 => ("convert", "f32_u32"),
|
|
Self::Convert_F32_I64 => ("convert", "f32_i64"),
|
|
Self::Convert_F32_U64 => ("convert", "f32_u64"),
|
|
Self::Demote_F32_F64 => ("demote", "f32_f64"),
|
|
Self::Convert_F64_I32 => ("convert", "f64_i32"),
|
|
Self::Convert_F64_U32 => ("convert", "f64_u32"),
|
|
Self::Convert_F64_I64 => ("convert", "f64_i64"),
|
|
Self::Convert_F64_U64 => ("convert", "f64_u64"),
|
|
Self::Promote_F64_F32 => ("promote", "f64_f32"),
|
|
Self::Reinterpret_I32_F32 => ("reinterpret", "i32_f32"),
|
|
Self::Reinterpret_I64_F64 => ("reinterpret", "i64_f64"),
|
|
Self::Reinterpret_F32_I32 => ("reinterpret", "f32_i32"),
|
|
Self::Reinterpret_F64_I64 => ("reinterpret", "f64_i64"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&Instruction> for UnOp {
|
|
type Error = ();
|
|
|
|
fn try_from(inst: &Instruction) -> Result<Self, Self::Error> {
|
|
let result = match inst {
|
|
Instruction::I32Eqz => Self::Eqz_I32,
|
|
Instruction::I64Eqz => Self::Eqz_I64,
|
|
Instruction::I32Clz => Self::Clz_I32,
|
|
Instruction::I32Ctz => Self::Ctz_I32,
|
|
Instruction::I32Popcnt => Self::Popcnt_I32,
|
|
Instruction::I64Clz => Self::Clz_I64,
|
|
Instruction::I64Ctz => Self::Ctz_I64,
|
|
Instruction::I64Popcnt => Self::Popcnt_I64,
|
|
Instruction::F32Abs | Instruction::F64Abs => Self::Abs_FN,
|
|
Instruction::F32Neg | Instruction::F64Neg => Self::Neg_FN,
|
|
Instruction::F32Ceil | Instruction::F64Ceil => Self::Ceil_FN,
|
|
Instruction::F32Floor | Instruction::F64Floor => Self::Floor_FN,
|
|
Instruction::F32Trunc | Instruction::F64Trunc => Self::Trunc_FN,
|
|
Instruction::F32Nearest | Instruction::F64Nearest => Self::Nearest_FN,
|
|
Instruction::F32Sqrt | Instruction::F64Sqrt => Self::Sqrt_FN,
|
|
Instruction::I32WrapI64 => Self::Wrap_I32_I64,
|
|
Instruction::I32TruncSF32 => Self::Trunc_I32_F32,
|
|
Instruction::I32TruncUF32 => Self::Trunc_U32_F32,
|
|
Instruction::I32TruncSF64 => Self::Trunc_I32_F64,
|
|
Instruction::I32TruncUF64 => Self::Trunc_U32_F64,
|
|
Instruction::I64ExtendSI32 => Self::Extend_I64_I32,
|
|
Instruction::I64ExtendUI32 => Self::Extend_U64_I32,
|
|
Instruction::I64TruncSF32 => Self::Trunc_I64_F32,
|
|
Instruction::I64TruncUF32 => Self::Trunc_U64_F32,
|
|
Instruction::I64TruncSF64 => Self::Trunc_I64_F64,
|
|
Instruction::I64TruncUF64 => Self::Trunc_U64_F64,
|
|
Instruction::F32ConvertSI32 => Self::Convert_F32_I32,
|
|
Instruction::F32ConvertUI32 => Self::Convert_F32_U32,
|
|
Instruction::F32ConvertSI64 => Self::Convert_F32_I64,
|
|
Instruction::F32ConvertUI64 => Self::Convert_F32_U64,
|
|
Instruction::F32DemoteF64 => Self::Demote_F32_F64,
|
|
Instruction::F64ConvertSI32 => Self::Convert_F64_I32,
|
|
Instruction::F64ConvertUI32 => Self::Convert_F64_U32,
|
|
Instruction::F64ConvertSI64 => Self::Convert_F64_I64,
|
|
Instruction::F64ConvertUI64 => Self::Convert_F64_U64,
|
|
Instruction::F64PromoteF32 => Self::Promote_F64_F32,
|
|
Instruction::I32ReinterpretF32 => Self::Reinterpret_I32_F32,
|
|
Instruction::I64ReinterpretF64 => Self::Reinterpret_I64_F64,
|
|
Instruction::F32ReinterpretI32 => Self::Reinterpret_F32_I32,
|
|
Instruction::F64ReinterpretI64 => Self::Reinterpret_F64_I64,
|
|
_ => return Err(()),
|
|
};
|
|
|
|
Ok(result)
|
|
}
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Clone, Copy)]
|
|
pub enum BinOp {
|
|
Eq_I32,
|
|
Ne_I32,
|
|
LtS_I32,
|
|
LtU_I32,
|
|
GtS_I32,
|
|
GtU_I32,
|
|
LeS_I32,
|
|
LeU_I32,
|
|
GeS_I32,
|
|
GeU_I32,
|
|
Eq_I64,
|
|
Ne_I64,
|
|
LtS_I64,
|
|
LtU_I64,
|
|
GtS_I64,
|
|
GtU_I64,
|
|
LeS_I64,
|
|
LeU_I64,
|
|
GeS_I64,
|
|
GeU_I64,
|
|
Add_I32,
|
|
Sub_I32,
|
|
Mul_I32,
|
|
DivS_I32,
|
|
DivU_I32,
|
|
RemS_I32,
|
|
RemU_I32,
|
|
And_I32,
|
|
Or_I32,
|
|
Xor_I32,
|
|
Shl_I32,
|
|
ShrS_I32,
|
|
ShrU_I32,
|
|
Rotl_I32,
|
|
Rotr_I32,
|
|
Add_I64,
|
|
Sub_I64,
|
|
Mul_I64,
|
|
DivS_I64,
|
|
DivU_I64,
|
|
RemS_I64,
|
|
RemU_I64,
|
|
And_I64,
|
|
Or_I64,
|
|
Xor_I64,
|
|
Shl_I64,
|
|
ShrS_I64,
|
|
ShrU_I64,
|
|
Rotl_I64,
|
|
Rotr_I64,
|
|
Eq_FN,
|
|
Ne_FN,
|
|
Lt_FN,
|
|
Gt_FN,
|
|
Le_FN,
|
|
Ge_FN,
|
|
Add_FN,
|
|
Sub_FN,
|
|
Mul_FN,
|
|
Div_FN,
|
|
Min_FN,
|
|
Max_FN,
|
|
Copysign_FN,
|
|
}
|
|
|
|
impl BinOp {
|
|
pub fn as_operator(self) -> Option<&'static str> {
|
|
let op = match self {
|
|
Self::Add_FN => "+",
|
|
Self::Sub_FN => "-",
|
|
Self::Mul_FN => "*",
|
|
Self::Div_FN => "/",
|
|
Self::RemS_I32 | Self::RemU_I32 | Self::RemS_I64 | Self::RemU_I64 => "%",
|
|
_ => return None,
|
|
};
|
|
|
|
Some(op)
|
|
}
|
|
|
|
pub fn as_name(self) -> (&'static str, &'static str) {
|
|
match self {
|
|
Self::Eq_I32 => ("eq", "i32"),
|
|
Self::Ne_I32 => ("ne", "i32"),
|
|
Self::LtS_I32 => ("lt", "i32"),
|
|
Self::LtU_I32 => ("lt", "u32"),
|
|
Self::GtS_I32 => ("gt", "i32"),
|
|
Self::GtU_I32 => ("gt", "u32"),
|
|
Self::LeS_I32 => ("le", "i32"),
|
|
Self::LeU_I32 => ("le", "u32"),
|
|
Self::GeS_I32 => ("ge", "i32"),
|
|
Self::GeU_I32 => ("ge", "u32"),
|
|
Self::Eq_I64 => ("eq", "i64"),
|
|
Self::Ne_I64 => ("ne", "i64"),
|
|
Self::LtS_I64 => ("lt", "i64"),
|
|
Self::LtU_I64 => ("lt", "u64"),
|
|
Self::GtS_I64 => ("gt", "i64"),
|
|
Self::GtU_I64 => ("gt", "u64"),
|
|
Self::LeS_I64 => ("le", "i64"),
|
|
Self::LeU_I64 => ("le", "u64"),
|
|
Self::GeS_I64 => ("ge", "i64"),
|
|
Self::GeU_I64 => ("ge", "u64"),
|
|
Self::Add_I32 => ("add", "i32"),
|
|
Self::Sub_I32 => ("sub", "i32"),
|
|
Self::Mul_I32 => ("mul", "i32"),
|
|
Self::DivS_I32 => ("div", "i32"),
|
|
Self::DivU_I32 => ("div", "u32"),
|
|
Self::RemS_I32 => ("rem", "i32"),
|
|
Self::RemU_I32 => ("rem", "u32"),
|
|
Self::And_I32 => ("band", "i32"),
|
|
Self::Or_I32 => ("bor", "i32"),
|
|
Self::Xor_I32 => ("bxor", "i32"),
|
|
Self::Shl_I32 => ("shl", "i32"),
|
|
Self::ShrS_I32 => ("shr", "i32"),
|
|
Self::ShrU_I32 => ("shr", "u32"),
|
|
Self::Rotl_I32 => ("rotl", "i32"),
|
|
Self::Rotr_I32 => ("rotr", "i32"),
|
|
Self::Add_I64 => ("add", "i64"),
|
|
Self::Sub_I64 => ("sub", "i64"),
|
|
Self::Mul_I64 => ("mul", "i64"),
|
|
Self::DivS_I64 => ("div", "i64"),
|
|
Self::DivU_I64 => ("div", "u64"),
|
|
Self::RemS_I64 => ("rem", "i64"),
|
|
Self::RemU_I64 => ("rem", "u64"),
|
|
Self::And_I64 => ("band", "i64"),
|
|
Self::Or_I64 => ("bor", "i64"),
|
|
Self::Xor_I64 => ("bxor", "i64"),
|
|
Self::Shl_I64 => ("shl", "i64"),
|
|
Self::ShrS_I64 => ("shr", "i64"),
|
|
Self::ShrU_I64 => ("shr", "u64"),
|
|
Self::Rotl_I64 => ("rotl", "i64"),
|
|
Self::Rotr_I64 => ("rotr", "i64"),
|
|
Self::Eq_FN => ("eq", "num"),
|
|
Self::Ne_FN => ("ne", "num"),
|
|
Self::Lt_FN => ("lt", "num"),
|
|
Self::Gt_FN => ("gt", "num"),
|
|
Self::Le_FN => ("le", "num"),
|
|
Self::Ge_FN => ("ge", "num"),
|
|
Self::Add_FN => ("add", "num"),
|
|
Self::Sub_FN => ("sub", "num"),
|
|
Self::Mul_FN => ("mul", "num"),
|
|
Self::Div_FN => ("div", "num"),
|
|
Self::Min_FN => ("math", "min"),
|
|
Self::Max_FN => ("math", "max"),
|
|
Self::Copysign_FN => ("copysign", "num"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&Instruction> for BinOp {
|
|
type Error = ();
|
|
|
|
fn try_from(inst: &Instruction) -> Result<Self, Self::Error> {
|
|
let result = match inst {
|
|
Instruction::I32Eq => Self::Eq_I32,
|
|
Instruction::I32Ne => Self::Ne_I32,
|
|
Instruction::I32LtS => Self::LtS_I32,
|
|
Instruction::I32LtU => Self::LtU_I32,
|
|
Instruction::I32GtS => Self::GtS_I32,
|
|
Instruction::I32GtU => Self::GtU_I32,
|
|
Instruction::I32LeS => Self::LeS_I32,
|
|
Instruction::I32LeU => Self::LeU_I32,
|
|
Instruction::I32GeS => Self::GeS_I32,
|
|
Instruction::I32GeU => Self::GeU_I32,
|
|
Instruction::I64Eq => Self::Eq_I64,
|
|
Instruction::I64Ne => Self::Ne_I64,
|
|
Instruction::I64LtS => Self::LtS_I64,
|
|
Instruction::I64LtU => Self::LtU_I64,
|
|
Instruction::I64GtS => Self::GtS_I64,
|
|
Instruction::I64GtU => Self::GtU_I64,
|
|
Instruction::I64LeS => Self::LeS_I64,
|
|
Instruction::I64LeU => Self::LeU_I64,
|
|
Instruction::I64GeS => Self::GeS_I64,
|
|
Instruction::I64GeU => Self::GeU_I64,
|
|
Instruction::I32Add => Self::Add_I32,
|
|
Instruction::I32Sub => Self::Sub_I32,
|
|
Instruction::I32Mul => Self::Mul_I32,
|
|
Instruction::I32DivS => Self::DivS_I32,
|
|
Instruction::I32DivU => Self::DivU_I32,
|
|
Instruction::I32RemS => Self::RemS_I32,
|
|
Instruction::I32RemU => Self::RemU_I32,
|
|
Instruction::I32And => Self::And_I32,
|
|
Instruction::I32Or => Self::Or_I32,
|
|
Instruction::I32Xor => Self::Xor_I32,
|
|
Instruction::I32Shl => Self::Shl_I32,
|
|
Instruction::I32ShrS => Self::ShrS_I32,
|
|
Instruction::I32ShrU => Self::ShrU_I32,
|
|
Instruction::I32Rotl => Self::Rotl_I32,
|
|
Instruction::I32Rotr => Self::Rotr_I32,
|
|
Instruction::I64Add => Self::Add_I64,
|
|
Instruction::I64Sub => Self::Sub_I64,
|
|
Instruction::I64Mul => Self::Mul_I64,
|
|
Instruction::I64DivS => Self::DivS_I64,
|
|
Instruction::I64DivU => Self::DivU_I64,
|
|
Instruction::I64RemS => Self::RemS_I64,
|
|
Instruction::I64RemU => Self::RemU_I64,
|
|
Instruction::I64And => Self::And_I64,
|
|
Instruction::I64Or => Self::Or_I64,
|
|
Instruction::I64Xor => Self::Xor_I64,
|
|
Instruction::I64Shl => Self::Shl_I64,
|
|
Instruction::I64ShrS => Self::ShrS_I64,
|
|
Instruction::I64ShrU => Self::ShrU_I64,
|
|
Instruction::I64Rotl => Self::Rotl_I64,
|
|
Instruction::I64Rotr => Self::Rotr_I64,
|
|
Instruction::F32Eq | Instruction::F64Eq => Self::Eq_FN,
|
|
Instruction::F32Ne | Instruction::F64Ne => Self::Ne_FN,
|
|
Instruction::F32Lt | Instruction::F64Lt => Self::Lt_FN,
|
|
Instruction::F32Gt | Instruction::F64Gt => Self::Gt_FN,
|
|
Instruction::F32Le | Instruction::F64Le => Self::Le_FN,
|
|
Instruction::F32Ge | Instruction::F64Ge => Self::Ge_FN,
|
|
Instruction::F32Add | Instruction::F64Add => Self::Add_FN,
|
|
Instruction::F32Sub | Instruction::F64Sub => Self::Sub_FN,
|
|
Instruction::F32Mul | Instruction::F64Mul => Self::Mul_FN,
|
|
Instruction::F32Div | Instruction::F64Div => Self::Div_FN,
|
|
Instruction::F32Min | Instruction::F64Min => Self::Min_FN,
|
|
Instruction::F32Max | Instruction::F64Max => Self::Max_FN,
|
|
Instruction::F32Copysign | Instruction::F64Copysign => Self::Copysign_FN,
|
|
_ => {
|
|
return Err(());
|
|
}
|
|
};
|
|
|
|
Ok(result)
|
|
}
|
|
}
|