waffle/src/op_traits.rs

425 lines
15 KiB
Rust
Raw Normal View History

2021-11-13 03:41:32 -06:00
//! Metadata on operators.
use crate::ir::{Module, SignatureId, ValueId};
2021-11-13 03:41:32 -06:00
use anyhow::{bail, Result};
2021-11-13 04:32:05 -06:00
use wasmparser::{Operator, Type};
2021-11-13 03:41:32 -06:00
2021-11-13 04:32:05 -06:00
pub fn op_inputs(
module: &Module,
my_sig: SignatureId,
my_locals: &[Type],
op_stack: &[(Type, ValueId)],
2021-11-13 04:32:05 -06:00
op: &Operator<'_>,
) -> Result<Vec<Type>> {
2021-11-13 03:41:32 -06:00
match op {
&Operator::Unreachable | &Operator::Nop => Ok(vec![]),
2021-11-13 04:32:05 -06:00
&Operator::Call { function_index } => {
let sig = module.funcs[function_index as usize].sig();
Ok(Vec::from(module.signatures[sig].params.clone()))
}
2021-11-13 17:09:47 -06:00
&Operator::CallIndirect { index, .. } => {
let mut params = vec![Type::I32];
params.extend_from_slice(&module.signatures[index as usize].params[..]);
Ok(params)
}
2021-11-13 04:32:05 -06:00
&Operator::Return => Ok(Vec::from(module.signatures[my_sig].returns.clone())),
&Operator::LocalSet { local_index } | &Operator::LocalTee { local_index } => {
Ok(vec![my_locals[local_index as usize]])
}
&Operator::LocalGet { .. } => Ok(vec![]),
&Operator::Select => {
let val_ty = op_stack[op_stack.len() - 2].0;
Ok(vec![val_ty, val_ty, Type::I32])
}
&Operator::TypedSelect { ty } => Ok(vec![ty, ty, Type::I32]),
&Operator::GlobalGet { .. } => Ok(vec![]),
&Operator::GlobalSet { global_index } => Ok(vec![module.globals[global_index as usize]]),
Operator::I32Load { .. }
| Operator::I64Load { .. }
| Operator::F32Load { .. }
| Operator::F64Load { .. }
| Operator::I32Load8S { .. }
| Operator::I32Load8U { .. }
| Operator::I32Load16S { .. }
| Operator::I32Load16U { .. }
| Operator::I64Load8S { .. }
| Operator::I64Load8U { .. }
| Operator::I64Load16S { .. }
| Operator::I64Load16U { .. }
| Operator::I64Load32S { .. }
| Operator::I64Load32U { .. } => Ok(vec![Type::I32]),
Operator::I32Store { .. } => Ok(vec![Type::I32, Type::I32]),
Operator::I64Store { .. } => Ok(vec![Type::I32, Type::I64]),
Operator::F32Store { .. } => Ok(vec![Type::I32, Type::F32]),
Operator::F64Store { .. } => Ok(vec![Type::I32, Type::F64]),
Operator::I32Store8 { .. } => Ok(vec![Type::I32, Type::I32]),
Operator::I32Store16 { .. } => Ok(vec![Type::I32, Type::I32]),
Operator::I64Store8 { .. } => Ok(vec![Type::I32, Type::I64]),
Operator::I64Store16 { .. } => Ok(vec![Type::I32, Type::I64]),
Operator::I64Store32 { .. } => Ok(vec![Type::I32, Type::I64]),
Operator::I32Const { .. }
| Operator::I64Const { .. }
| Operator::F32Const { .. }
| Operator::F64Const { .. } => Ok(vec![]),
Operator::I32Eqz => Ok(vec![Type::I32]),
Operator::I32Eq
| Operator::I32Ne
| Operator::I32LtS
| Operator::I32LtU
| Operator::I32GtS
| Operator::I32GtU
| Operator::I32LeS
| Operator::I32LeU
| Operator::I32GeS
| Operator::I32GeU => Ok(vec![Type::I32, Type::I32]),
Operator::I64Eqz => Ok(vec![Type::I64]),
Operator::I64Eq
| Operator::I64Ne
| Operator::I64LtS
| Operator::I64LtU
| Operator::I64GtU
| Operator::I64GtS
| Operator::I64LeS
| Operator::I64LeU
| Operator::I64GeS
| Operator::I64GeU => Ok(vec![Type::I64, Type::I64]),
Operator::F32Eq
| Operator::F32Ne
| Operator::F32Lt
| Operator::F32Gt
| Operator::F32Le
| Operator::F32Ge => Ok(vec![Type::F32, Type::F32]),
Operator::F64Eq
| Operator::F64Ne
| Operator::F64Lt
| Operator::F64Gt
| Operator::F64Le
| Operator::F64Ge => Ok(vec![Type::F64, Type::F64]),
Operator::I32Clz | Operator::I32Ctz | Operator::I32Popcnt => Ok(vec![Type::I32]),
Operator::I32Add
| Operator::I32Sub
| Operator::I32Mul
| Operator::I32DivS
| Operator::I32DivU
| Operator::I32RemS
| Operator::I32RemU
| Operator::I32And
| Operator::I32Or
| Operator::I32Xor
| Operator::I32Shl
| Operator::I32ShrS
| Operator::I32ShrU
| Operator::I32Rotl
| Operator::I32Rotr => Ok(vec![Type::I32, Type::I32]),
Operator::I64Clz | Operator::I64Ctz | Operator::I64Popcnt => Ok(vec![Type::I64]),
Operator::I64Add
| Operator::I64Sub
| Operator::I64Mul
| Operator::I64DivS
| Operator::I64DivU
| Operator::I64RemS
| Operator::I64RemU
| Operator::I64And
| Operator::I64Or
| Operator::I64Xor
| Operator::I64Shl
| Operator::I64ShrS
| Operator::I64ShrU
| Operator::I64Rotl
| Operator::I64Rotr => Ok(vec![Type::I64, Type::I64]),
Operator::F32Abs
| Operator::F32Neg
| Operator::F32Ceil
| Operator::F32Floor
| Operator::F32Trunc
| Operator::F32Nearest
| Operator::F32Sqrt => Ok(vec![Type::F32]),
Operator::F32Add
| Operator::F32Sub
| Operator::F32Mul
| Operator::F32Div
| Operator::F32Min
| Operator::F32Max
| Operator::F32Copysign => Ok(vec![Type::F32, Type::F32]),
Operator::F64Abs
| Operator::F64Neg
| Operator::F64Ceil
| Operator::F64Floor
| Operator::F64Trunc
| Operator::F64Nearest
| Operator::F64Sqrt => Ok(vec![Type::F64]),
Operator::F64Add
| Operator::F64Sub
| Operator::F64Mul
| Operator::F64Div
| Operator::F64Min
| Operator::F64Max
| Operator::F64Copysign => Ok(vec![Type::F64, Type::F64]),
Operator::I32WrapI64 => Ok(vec![Type::I64]),
Operator::I32TruncF32S => Ok(vec![Type::F32]),
Operator::I32TruncF32U => Ok(vec![Type::F32]),
Operator::I32TruncF64S => Ok(vec![Type::F64]),
Operator::I32TruncF64U => Ok(vec![Type::F64]),
Operator::I64ExtendI32S => Ok(vec![Type::I32]),
Operator::I64ExtendI32U => Ok(vec![Type::I32]),
Operator::I64TruncF32S => Ok(vec![Type::F32]),
Operator::I64TruncF32U => Ok(vec![Type::F32]),
Operator::I64TruncF64S => Ok(vec![Type::F64]),
Operator::I64TruncF64U => Ok(vec![Type::F64]),
Operator::F32ConvertI32S => Ok(vec![Type::I32]),
Operator::F32ConvertI32U => Ok(vec![Type::I32]),
Operator::F32ConvertI64S => Ok(vec![Type::I64]),
Operator::F32ConvertI64U => Ok(vec![Type::I64]),
Operator::F32DemoteF64 => Ok(vec![Type::F64]),
Operator::F64ConvertI32S => Ok(vec![Type::I32]),
Operator::F64ConvertI32U => Ok(vec![Type::I32]),
Operator::F64ConvertI64S => Ok(vec![Type::I64]),
Operator::F64ConvertI64U => Ok(vec![Type::I64]),
Operator::F64PromoteF32 => Ok(vec![Type::F32]),
Operator::I32Extend8S => Ok(vec![Type::I32]),
Operator::I32Extend16S => Ok(vec![Type::I32]),
Operator::I64Extend8S => Ok(vec![Type::I64]),
Operator::I64Extend16S => Ok(vec![Type::I64]),
Operator::I64Extend32S => Ok(vec![Type::I64]),
Operator::I32TruncSatF32S => Ok(vec![Type::F32]),
Operator::I32TruncSatF32U => Ok(vec![Type::F32]),
Operator::I32TruncSatF64S => Ok(vec![Type::F64]),
Operator::I32TruncSatF64U => Ok(vec![Type::F64]),
Operator::I64TruncSatF32S => Ok(vec![Type::F32]),
Operator::I64TruncSatF32U => Ok(vec![Type::F32]),
Operator::I64TruncSatF64S => Ok(vec![Type::F64]),
Operator::I64TruncSatF64U => Ok(vec![Type::F64]),
Operator::TableGet { .. } => Ok(vec![Type::I32]),
Operator::TableSet { table } => Ok(vec![Type::I32, module.tables[*table as usize]]),
Operator::TableGrow { .. } => Ok(vec![Type::I32]),
Operator::TableSize { .. } => Ok(vec![]),
2021-11-13 16:23:22 -06:00
2021-11-13 03:41:32 -06:00
_ => bail!("Unknown operator in op_inputs(): {:?}", op),
}
}
pub fn op_outputs(
module: &Module,
my_locals: &[Type],
op_stack: &[(Type, ValueId)],
op: &Operator<'_>,
) -> Result<Vec<Type>> {
2021-11-13 03:41:32 -06:00
match op {
&Operator::Unreachable | &Operator::Nop => Ok(vec![]),
2021-11-13 04:32:05 -06:00
&Operator::Call { function_index } => {
let sig = module.funcs[function_index as usize].sig();
Ok(Vec::from(module.signatures[sig].returns.clone()))
}
2021-11-13 17:09:47 -06:00
&Operator::CallIndirect { index, .. } => {
Ok(Vec::from(module.signatures[index as usize].returns.clone()))
}
2021-11-13 04:32:05 -06:00
&Operator::Return => Ok(vec![]),
&Operator::LocalSet { .. } | &Operator::LocalTee { .. } => Ok(vec![]),
&Operator::LocalGet { local_index } => Ok(vec![my_locals[local_index as usize]]),
&Operator::Select => {
let val_ty = op_stack[op_stack.len() - 2].0;
Ok(vec![val_ty])
}
&Operator::TypedSelect { ty } => Ok(vec![ty]),
&Operator::GlobalGet { global_index } => Ok(vec![module.globals[global_index as usize]]),
&Operator::GlobalSet { .. } => Ok(vec![]),
Operator::I32Load { .. }
| Operator::I64Load { .. }
| Operator::F32Load { .. }
| Operator::F64Load { .. }
| Operator::I32Load8S { .. }
| Operator::I32Load8U { .. }
| Operator::I32Load16S { .. }
| Operator::I32Load16U { .. } => Ok(vec![Type::I32]),
Operator::I64Load8S { .. }
| Operator::I64Load8U { .. }
| Operator::I64Load16S { .. }
| Operator::I64Load16U { .. }
| Operator::I64Load32S { .. }
| Operator::I64Load32U { .. } => Ok(vec![Type::I64]),
Operator::I32Store { .. } => Ok(vec![]),
Operator::I64Store { .. } => Ok(vec![]),
Operator::F32Store { .. } => Ok(vec![]),
Operator::F64Store { .. } => Ok(vec![]),
Operator::I32Store8 { .. } => Ok(vec![]),
Operator::I32Store16 { .. } => Ok(vec![]),
Operator::I64Store8 { .. } => Ok(vec![]),
Operator::I64Store16 { .. } => Ok(vec![]),
Operator::I64Store32 { .. } => Ok(vec![]),
Operator::I32Const { .. } => Ok(vec![Type::I32]),
Operator::I64Const { .. } => Ok(vec![Type::I64]),
Operator::F32Const { .. } => Ok(vec![Type::F32]),
Operator::F64Const { .. } => Ok(vec![Type::F64]),
Operator::I32Eqz
| Operator::I32Eq
| Operator::I32Ne
| Operator::I32LtS
| Operator::I32LtU
| Operator::I32GtS
| Operator::I32GtU
| Operator::I32LeS
| Operator::I32LeU
| Operator::I32GeS
| Operator::I32GeU
| Operator::I64Eqz
| Operator::I64Eq
| Operator::I64Ne
| Operator::I64LtS
| Operator::I64LtU
| Operator::I64GtU
| Operator::I64GtS
| Operator::I64LeS
| Operator::I64LeU
| Operator::I64GeS
| Operator::I64GeU
| Operator::F32Eq
| Operator::F32Ne
| Operator::F32Lt
| Operator::F32Gt
| Operator::F32Le
| Operator::F32Ge
| Operator::F64Eq
| Operator::F64Ne
| Operator::F64Lt
| Operator::F64Gt
| Operator::F64Le
| Operator::F64Ge => Ok(vec![Type::I32]),
Operator::I32Clz
| Operator::I32Ctz
| Operator::I32Popcnt
| Operator::I32Add
| Operator::I32Sub
| Operator::I32Mul
| Operator::I32DivS
| Operator::I32DivU
| Operator::I32RemS
| Operator::I32RemU
| Operator::I32And
| Operator::I32Or
| Operator::I32Xor
| Operator::I32Shl
| Operator::I32ShrS
| Operator::I32ShrU
| Operator::I32Rotl
| Operator::I32Rotr => Ok(vec![Type::I32]),
Operator::I64Clz
| Operator::I64Ctz
| Operator::I64Popcnt
| Operator::I64Add
| Operator::I64Sub
| Operator::I64Mul
| Operator::I64DivS
| Operator::I64DivU
| Operator::I64RemS
| Operator::I64RemU
| Operator::I64And
| Operator::I64Or
| Operator::I64Xor
| Operator::I64Shl
| Operator::I64ShrS
| Operator::I64ShrU
| Operator::I64Rotl
| Operator::I64Rotr => Ok(vec![Type::I64]),
Operator::F32Abs
| Operator::F32Neg
| Operator::F32Ceil
| Operator::F32Floor
| Operator::F32Trunc
| Operator::F32Nearest
| Operator::F32Sqrt
| Operator::F32Add
| Operator::F32Sub
| Operator::F32Mul
| Operator::F32Div
| Operator::F32Min
| Operator::F32Max
| Operator::F32Copysign => Ok(vec![Type::F32]),
Operator::F64Abs
| Operator::F64Neg
| Operator::F64Ceil
| Operator::F64Floor
| Operator::F64Trunc
| Operator::F64Nearest
| Operator::F64Sqrt
| Operator::F64Add
| Operator::F64Sub
| Operator::F64Mul
| Operator::F64Div
| Operator::F64Min
| Operator::F64Max
| Operator::F64Copysign => Ok(vec![Type::F64]),
Operator::I32WrapI64 => Ok(vec![Type::I32]),
Operator::I32TruncF32S => Ok(vec![Type::I32]),
Operator::I32TruncF32U => Ok(vec![Type::I32]),
Operator::I32TruncF64S => Ok(vec![Type::I32]),
Operator::I32TruncF64U => Ok(vec![Type::I32]),
Operator::I64ExtendI32S => Ok(vec![Type::I64]),
Operator::I64ExtendI32U => Ok(vec![Type::I64]),
Operator::I64TruncF32S => Ok(vec![Type::I64]),
Operator::I64TruncF32U => Ok(vec![Type::I64]),
Operator::I64TruncF64S => Ok(vec![Type::I64]),
Operator::I64TruncF64U => Ok(vec![Type::I64]),
Operator::F32ConvertI32S => Ok(vec![Type::F32]),
Operator::F32ConvertI32U => Ok(vec![Type::F32]),
Operator::F32ConvertI64S => Ok(vec![Type::F32]),
Operator::F32ConvertI64U => Ok(vec![Type::F32]),
Operator::F32DemoteF64 => Ok(vec![Type::F32]),
Operator::F64ConvertI32S => Ok(vec![Type::F64]),
Operator::F64ConvertI32U => Ok(vec![Type::F64]),
Operator::F64ConvertI64S => Ok(vec![Type::F64]),
Operator::F64ConvertI64U => Ok(vec![Type::F64]),
Operator::F64PromoteF32 => Ok(vec![Type::F64]),
Operator::I32Extend8S => Ok(vec![Type::I32]),
Operator::I32Extend16S => Ok(vec![Type::I32]),
Operator::I64Extend8S => Ok(vec![Type::I64]),
Operator::I64Extend16S => Ok(vec![Type::I64]),
Operator::I64Extend32S => Ok(vec![Type::I64]),
Operator::I32TruncSatF32S => Ok(vec![Type::I32]),
Operator::I32TruncSatF32U => Ok(vec![Type::I32]),
Operator::I32TruncSatF64S => Ok(vec![Type::I32]),
Operator::I32TruncSatF64U => Ok(vec![Type::I32]),
Operator::I64TruncSatF32S => Ok(vec![Type::I64]),
Operator::I64TruncSatF32U => Ok(vec![Type::I64]),
Operator::I64TruncSatF64S => Ok(vec![Type::I64]),
Operator::I64TruncSatF64U => Ok(vec![Type::I64]),
Operator::TableGet { table } => Ok(vec![module.tables[*table as usize]]),
Operator::TableSet { .. } => Ok(vec![]),
Operator::TableGrow { .. } => Ok(vec![]),
Operator::TableSize { .. } => Ok(vec![Type::I32]),
2021-11-13 16:23:22 -06:00
2021-11-13 03:41:32 -06:00
_ => bail!("Unknown operator in op_outputs(): {:?}", op),
}
}