diff --git a/src/bin/waffle-util.rs b/src/bin/waffle-util.rs index c409e53..f95010f 100644 --- a/src/bin/waffle-util.rs +++ b/src/bin/waffle-util.rs @@ -46,7 +46,7 @@ fn main() -> Result<()> { let bytes = std::fs::read(wasm)?; debug!("Loaded {} bytes of Wasm data", bytes.len()); let module = Module::from_wasm_bytes(&bytes[..])?; - println!("{:?}", module); + println!("{}", module.display()); } Command::RoundTrip { input, output } => { let bytes = std::fs::read(input)?; diff --git a/src/frontend.rs b/src/frontend.rs index 4a6d18d..145e66a 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -11,7 +11,7 @@ use fxhash::{FxHashMap, FxHashSet}; use log::trace; use std::convert::TryFrom; use wasmparser::{ - Ieee32, Ieee64, ImportSectionEntryType, Parser, Payload, Type, TypeDef, TypeOrFuncType, + Ieee32, Ieee64, ImportSectionEntryType, Parser, Payload, TypeDef, TypeOrFuncType, }; pub fn wasm_to_ir(bytes: &[u8]) -> Result> { @@ -37,7 +37,7 @@ fn handle_payload<'a>( for _ in 0..reader.get_count() { let ty = reader.read()?; if let TypeDef::Func(fty) = ty { - module.frontend_add_signature(fty); + module.frontend_add_signature(fty.into()); } } } @@ -49,10 +49,10 @@ fn handle_payload<'a>( *next_func += 1; } ImportSectionEntryType::Global(ty) => { - module.frontend_add_global(ty.content_type); + module.frontend_add_global(ty.content_type.into()); } ImportSectionEntryType::Table(ty) => { - module.frontend_add_table(ty.element_type); + module.frontend_add_table(ty.element_type.into()); } _ => {} } @@ -61,13 +61,13 @@ fn handle_payload<'a>( Payload::GlobalSection(mut reader) => { for _ in 0..reader.get_count() { let global = reader.read()?; - module.frontend_add_global(global.ty.content_type); + module.frontend_add_global(global.ty.content_type.into()); } } Payload::TableSection(mut reader) => { for _ in 0..reader.get_count() { let table = reader.read()?; - module.frontend_add_table(table.element_type); + module.frontend_add_table(table.element_type.into()); } } Payload::FunctionSection(mut reader) => { @@ -100,18 +100,18 @@ fn parse_body<'a>( let mut ret: FunctionBody = FunctionBody::default(); for ¶m in &module.signature(my_sig).params[..] { - ret.locals.push(param); + ret.locals.push(param.into()); } ret.n_params = module.signature(my_sig).params.len(); for &r in &module.signature(my_sig).returns[..] { - ret.rets.push(r); + ret.rets.push(r.into()); } let mut locals = body.get_locals_reader()?; for _ in 0..locals.get_count() { let (count, ty) = locals.read()?; for _ in 0..count { - ret.locals.push(ty); + ret.locals.push(ty.into()); } } let locals = ret.locals.clone(); @@ -124,12 +124,16 @@ fn parse_body<'a>( let mut builder = FunctionBodyBuilder::new(module, my_sig, &mut ret); let entry = Block::new(0); + builder.body.entry = entry; builder.locals.seal_block_preds(entry, &mut builder.body); builder.locals.start_block(entry); for (arg_idx, &arg_ty) in module.signature(my_sig).params.iter().enumerate() { let local_idx = Local::new(arg_idx); - let value = builder.body.add_value(ValueDef::Arg(arg_idx, arg_ty)); + builder.body.add_blockparam(entry, arg_ty); + let value = builder + .body + .add_value(ValueDef::BlockParam(entry, arg_idx, arg_ty)); trace!("defining local {} to value {}", local_idx, value); builder.locals.declare(local_idx, arg_ty); builder.locals.set(local_idx, value); @@ -1005,8 +1009,8 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> { fn block_params_and_results(&self, ty: TypeOrFuncType) -> (Vec, Vec) { match ty { - TypeOrFuncType::Type(Type::EmptyBlockType) => (vec![], vec![]), - TypeOrFuncType::Type(ret_ty) => (vec![], vec![ret_ty]), + TypeOrFuncType::Type(wasmparser::Type::EmptyBlockType) => (vec![], vec![]), + TypeOrFuncType::Type(ret_ty) => (vec![], vec![ret_ty.into()]), TypeOrFuncType::FuncType(sig_idx) => { let sig = &self.module.signature(Signature::from(sig_idx)); ( diff --git a/src/ir.rs b/src/ir.rs index 57cd133..eded1d6 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -2,7 +2,39 @@ use crate::entity; -pub use wasmparser::Type; +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Type { + I32, + I64, + F32, + F64, + V128, +} +impl From for Type { + fn from(ty: wasmparser::Type) -> Self { + match ty { + wasmparser::Type::I32 => Type::I32, + wasmparser::Type::I64 => Type::I64, + wasmparser::Type::F32 => Type::F32, + wasmparser::Type::F64 => Type::F64, + wasmparser::Type::V128 => Type::V128, + _ => panic!("Unsupported type: {:?}", ty), + } + } +} + +impl std::fmt::Display for Type { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let s = match self { + Type::I32 => "i32", + Type::I64 => "i64", + Type::F32 => "f32", + Type::F64 => "f64", + Type::V128 => "v128", + }; + write!(f, "{}", s) + } +} entity!(Signature, "sig"); entity!(Func, "func"); @@ -19,3 +51,5 @@ mod func; pub use func::*; mod value; pub use value::*; +mod display; +pub use display::*; diff --git a/src/ir/display.rs b/src/ir/display.rs new file mode 100644 index 0000000..7a9ff6b --- /dev/null +++ b/src/ir/display.rs @@ -0,0 +1,100 @@ +//! Displaying IR. + +use super::{FuncDecl, FunctionBody, Module, ValueDef}; + +use std::fmt::{Display, Formatter, Result as FmtResult}; + +pub struct FunctionBodyDisplay<'a>(pub(crate) &'a FunctionBody, pub(crate) &'a str); + +impl<'a> Display for FunctionBodyDisplay<'a> { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + let arg_tys = self + .0 + .locals + .values() + .take(self.0.n_params) + .map(|&ty| format!("{}", ty)) + .collect::>(); + let ret_tys = self + .0 + .rets + .iter() + .map(|&ty| format!("{}", ty)) + .collect::>(); + writeln!( + f, + "{}function({}) -> {} {{", + self.1, + arg_tys.join(", "), + ret_tys.join(", ") + )?; + + for (block_id, block) in self.0.blocks.entries() { + let block_params = block + .params + .iter() + .map(|(ty, val)| format!("{}: {}", val, ty)) + .collect::>(); + writeln!(f, "{} {}({}):", self.1, block_id, block_params.join(", "))?; + for &pred in &block.preds { + writeln!(f, "{} # pred: {}", self.1, pred)?; + } + for &succ in &block.succs { + writeln!(f, "{} # succ: {}", self.1, succ)?; + } + for &inst in &block.insts { + let inst = self.0.resolve_alias(inst); + match &self.0.values[inst] { + ValueDef::Operator(op, args, tys) => { + let args = args + .iter() + .map(|&v| { + let v = self.0.resolve_alias(v); + format!("{}", v) + }) + .collect::>(); + let tys = tys.iter().map(|&ty| format!("{}", ty)).collect::>(); + writeln!( + f, + "{} {} = {} {} # {}", + self.1, + inst, + op, + args.join(", "), + tys.join(", ") + )?; + } + ValueDef::PickOutput(val, idx, ty) => { + writeln!(f, "{} {} = {}.{} # {}", self.1, inst, val, idx, ty)?; + } + _ => unreachable!(), + } + } + } + + writeln!(f, "}}")?; + + Ok(()) + } +} + +pub struct ModuleDisplay<'a>(pub(crate) &'a Module<'a>); + +impl<'a> Display for ModuleDisplay<'a> { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + writeln!(f, "module {{")?; + for (func, func_decl) in self.0.funcs() { + match func_decl { + FuncDecl::Body(sig, body) => { + writeln!(f, " {}: {} =", func, sig)?; + writeln!(f, "{}", body.display(" "))?; + } + FuncDecl::Import(sig) => { + writeln!(f, " {}: {}", func, sig)?; + } + } + } + writeln!(f, "}}")?; + Ok(()) + } +} diff --git a/src/ir/func.rs b/src/ir/func.rs index af05f36..36f7427 100644 --- a/src/ir/func.rs +++ b/src/ir/func.rs @@ -1,6 +1,5 @@ -use super::{Block, Local, Signature, Value, ValueDef}; +use super::{Block, FunctionBodyDisplay, Local, Signature, Value, ValueDef, Type}; use crate::entity::EntityVec; -use wasmparser::Type; #[derive(Clone, Debug)] pub enum FuncDecl { @@ -139,6 +138,10 @@ impl FunctionBody { pub fn add_local(&mut self, ty: Type) -> Local { self.locals.push(ty) } + + pub fn display<'a>(&'a self, indent: &'a str) -> FunctionBodyDisplay<'a> { + FunctionBodyDisplay(self, indent) + } } #[derive(Clone, Debug, Default)] diff --git a/src/ir/module.rs b/src/ir/module.rs index fa8e211..d52ec24 100644 --- a/src/ir/module.rs +++ b/src/ir/module.rs @@ -1,21 +1,48 @@ -use super::{Func, FuncDecl, Global, Signature, Table}; +use super::{Func, FuncDecl, Global, ModuleDisplay, Signature, Table, Type}; use crate::entity::EntityVec; use crate::frontend; use anyhow::Result; use fxhash::FxHashSet; -use wasmparser::{FuncType, Type}; #[derive(Clone, Debug, Default)] pub struct Module<'a> { orig_bytes: &'a [u8], funcs: EntityVec, - signatures: EntityVec, + signatures: EntityVec, globals: EntityVec, tables: EntityVec, dirty_funcs: FxHashSet, } +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct SignatureData { + pub params: Vec, + pub returns: Vec, +} + +impl From<&wasmparser::FuncType> for SignatureData { + fn from(fty: &wasmparser::FuncType) -> Self { + Self { + params: fty + .params + .iter() + .map(|&ty| ty.into()) + .collect::>(), + returns: fty + .returns + .iter() + .map(|&ty| ty.into()) + .collect::>(), + } + } +} +impl From for SignatureData { + fn from(fty: wasmparser::FuncType) -> Self { + (&fty).into() + } +} + impl<'a> Module<'a> { pub(crate) fn with_orig_bytes(orig_bytes: &'a [u8]) -> Module<'a> { let mut m = Module::default(); @@ -32,7 +59,10 @@ impl<'a> Module<'a> { self.dirty_funcs.insert(id); &mut self.funcs[id] } - pub fn signature<'b>(&'b self, id: Signature) -> &'b FuncType { + pub fn funcs<'b>(&'b self) -> impl Iterator { + self.funcs.entries() + } + pub fn signature<'b>(&'b self, id: Signature) -> &'b SignatureData { &self.signatures[id] } pub fn global_ty(&self, id: Global) -> Type { @@ -42,7 +72,7 @@ impl<'a> Module<'a> { self.tables[id] } - pub(crate) fn frontend_add_signature(&mut self, ty: FuncType) { + pub(crate) fn frontend_add_signature(&mut self, ty: SignatureData) { self.signatures.push(ty); } pub(crate) fn frontend_add_func(&mut self, body: FuncDecl) { @@ -62,4 +92,11 @@ impl<'a> Module<'a> { pub fn to_wasm_bytes(&self) -> Result> { todo!() } + + pub fn display<'b>(&'b self) -> ModuleDisplay<'b> + where + 'b: 'a, + { + ModuleDisplay(self) + } } diff --git a/src/ir/value.rs b/src/ir/value.rs index da90b1e..64565d9 100644 --- a/src/ir/value.rs +++ b/src/ir/value.rs @@ -1,10 +1,8 @@ -use super::{Block, Value}; +use super::{Block, Value, Type}; use crate::Operator; -use wasmparser::Type; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum ValueDef { - Arg(usize, Type), BlockParam(Block, usize, Type), Operator(Operator, Vec, Vec), PickOutput(Value, usize, Type), @@ -15,7 +13,6 @@ pub enum ValueDef { impl ValueDef { pub fn visit_uses(&self, mut f: F) { match self { - &ValueDef::Arg { .. } => {} &ValueDef::BlockParam { .. } => {} &ValueDef::Operator(_, ref args, _) => { for &arg in args { @@ -30,7 +27,6 @@ impl ValueDef { pub fn update_uses(&mut self, mut f: F) { match self { - &mut ValueDef::Arg { .. } => {} &mut ValueDef::BlockParam { .. } => {} &mut ValueDef::Operator(_, ref mut args, _) => { for arg in args { diff --git a/src/op_traits.rs b/src/op_traits.rs index 9ec18c9..15f4894 100644 --- a/src/op_traits.rs +++ b/src/op_traits.rs @@ -1,10 +1,9 @@ //! Metadata on operators. use crate::entity::EntityVec; -use crate::ir::{Global, Local, Module, Signature, Table, Value}; +use crate::ir::{Global, Local, Module, Signature, Table, Value, Type}; use crate::Operator; use anyhow::Result; -use wasmparser::Type; pub fn op_inputs( module: &Module, @@ -651,6 +650,212 @@ pub fn op_effects(op: &Operator) -> Result> { } } +impl std::fmt::Display for Operator { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + &Operator::Unreachable => write!(f, "unreachable")?, + &Operator::Nop => write!(f, "nop")?, + + &Operator::Call { function_index } => write!(f, "call<{}>", function_index)?, + &Operator::CallIndirect { + sig_index, + table_index, + } => write!(f, "call_indirect<{}, {}>", sig_index, table_index)?, + &Operator::Return => write!(f, "return")?, + &Operator::LocalSet { local_index, .. } => write!(f, "local_set<{}>", local_index)?, + &Operator::LocalGet { local_index, .. } => write!(f, "local_get<{}>", local_index)?, + &Operator::LocalTee { local_index, .. } => write!(f, "local_tee<{}>", local_index)?, + + &Operator::Select => write!(f, "select")?, + &Operator::TypedSelect { ty } => write!(f, "typed_select<{}>", ty)?, + &Operator::GlobalGet { global_index, .. } => write!(f, "global_get<{}>", global_index)?, + &Operator::GlobalSet { global_index, .. } => write!(f, "global_set<{}>", global_index)?, + + Operator::I32Load { memory } => write!(f, "i32load<{}>", memory)?, + Operator::I32Load8S { memory } => write!(f, "i32load8s<{}>", memory)?, + Operator::I32Load8U { memory } => write!(f, "i32load8u<{}>", memory)?, + Operator::I32Load16S { memory } => write!(f, "i32load16s<{}>", memory)?, + Operator::I32Load16U { memory } => write!(f, "i32load16u<{}>", memory)?, + Operator::I64Load { memory } => write!(f, "i64load<{}>", memory)?, + Operator::I64Load8S { memory } => write!(f, "i64load8s<{}>", memory)?, + Operator::I64Load8U { memory } => write!(f, "i64load8u<{}>", memory)?, + Operator::I64Load16S { memory } => write!(f, "i64load16s<{}>", memory)?, + Operator::I64Load16U { memory } => write!(f, "i64load16u<{}>", memory)?, + Operator::I64Load32S { memory } => write!(f, "i64load32s<{}>", memory)?, + Operator::I64Load32U { memory } => write!(f, "i64load32u<{}>", memory)?, + Operator::F32Load { memory } => write!(f, "f32load<{}>", memory)?, + Operator::F64Load { memory } => write!(f, "f64load<{}>", memory)?, + + Operator::I32Store { memory } => write!(f, "i32store<{}>", memory)?, + Operator::I64Store { memory } => write!(f, "i64store<{}>", memory)?, + Operator::F32Store { memory } => write!(f, "f32store<{}>", memory)?, + Operator::F64Store { memory } => write!(f, "f642store<{}>", memory)?, + Operator::I32Store8 { memory } => write!(f, "i32store8<{}>", memory)?, + Operator::I32Store16 { memory } => write!(f, "i32store16<{}>", memory)?, + Operator::I64Store8 { memory } => write!(f, "i64store8<{}>", memory)?, + Operator::I64Store16 { memory } => write!(f, "i64store16<{}>", memory)?, + Operator::I64Store32 { memory } => write!(f, "i64store32<{}>", memory)?, + + Operator::I32Const { value } => write!(f, "i32const<{}>", value)?, + Operator::I64Const { value } => write!(f, "i64const<{}>", value)?, + Operator::F32Const { value } => write!(f, "f32const<{}>", value.bits())?, + Operator::F64Const { value } => write!(f, "f64const<{}>", value.bits())?, + + Operator::I32Eqz => write!(f, "i32eqz")?, + Operator::I32Eq => write!(f, "i32eq")?, + Operator::I32Ne => write!(f, "i32ne")?, + Operator::I32LtS => write!(f, "i32lts")?, + Operator::I32LtU => write!(f, "i32ltu")?, + Operator::I32GtS => write!(f, "i32gts")?, + Operator::I32GtU => write!(f, "i32gtu")?, + Operator::I32LeS => write!(f, "i32les")?, + Operator::I32LeU => write!(f, "i32leu")?, + Operator::I32GeS => write!(f, "i64ges")?, + Operator::I32GeU => write!(f, "i32geu")?, + Operator::I64Eqz => write!(f, "i64eqz")?, + Operator::I64Eq => write!(f, "i64eq")?, + Operator::I64Ne => write!(f, "i64ne")?, + Operator::I64LtS => write!(f, "i64lts")?, + Operator::I64LtU => write!(f, "i64ltu")?, + Operator::I64GtU => write!(f, "i64gtu")?, + Operator::I64GtS => write!(f, "i64gts")?, + Operator::I64LeS => write!(f, "i64les")?, + Operator::I64LeU => write!(f, "i64leu")?, + Operator::I64GeS => write!(f, "i64ges")?, + Operator::I64GeU => write!(f, "i64geu")?, + Operator::F32Eq => write!(f, "f32eq")?, + Operator::F32Ne => write!(f, "f32ne")?, + Operator::F32Lt => write!(f, "f32lt")?, + Operator::F32Gt => write!(f, "f32gt")?, + Operator::F32Le => write!(f, "f32le")?, + Operator::F32Ge => write!(f, "f32ge")?, + Operator::F64Eq => write!(f, "f64eq")?, + Operator::F64Ne => write!(f, "f64ne")?, + Operator::F64Lt => write!(f, "f64lt")?, + Operator::F64Gt => write!(f, "f64gt")?, + Operator::F64Le => write!(f, "f64le")?, + Operator::F64Ge => write!(f, "f64ge")?, + + Operator::I32Clz => write!(f, "i32clz")?, + Operator::I32Ctz => write!(f, "i32ctz")?, + Operator::I32Popcnt => write!(f, "i32popcnt")?, + Operator::I32Add => write!(f, "i32add")?, + Operator::I32Sub => write!(f, "i32sub")?, + Operator::I32Mul => write!(f, "i32mul")?, + Operator::I32And => write!(f, "i32and")?, + Operator::I32Or => write!(f, "i32or")?, + Operator::I32Xor => write!(f, "i32xor")?, + Operator::I32Shl => write!(f, "i32shl")?, + Operator::I32ShrS => write!(f, "i32shrs")?, + Operator::I32ShrU => write!(f, "i32shru")?, + Operator::I32Rotl => write!(f, "i32rotl")?, + Operator::I32Rotr => write!(f, "i32rotr")?, + + Operator::I32DivS => write!(f, "i32divs")?, + Operator::I32DivU => write!(f, "i32divu")?, + Operator::I32RemS => write!(f, "i32rems")?, + Operator::I32RemU => write!(f, "i32remu")?, + + Operator::I64Clz => write!(f, "i64clz")?, + Operator::I64Ctz => write!(f, "i64ctz")?, + Operator::I64Popcnt => write!(f, "i64popcnt")?, + Operator::I64Add => write!(f, "i64add")?, + Operator::I64Sub => write!(f, "i64sub")?, + Operator::I64Mul => write!(f, "i64mul")?, + Operator::I64And => write!(f, "i64and")?, + Operator::I64Or => write!(f, "i64or")?, + Operator::I64Xor => write!(f, "i64xor")?, + Operator::I64Shl => write!(f, "i64shl")?, + Operator::I64ShrS => write!(f, "i64shrs")?, + Operator::I64ShrU => write!(f, "i64shru")?, + Operator::I64Rotl => write!(f, "i64rotl")?, + Operator::I64Rotr => write!(f, "i64rotr")?, + + Operator::I64DivS => write!(f, "i64divs")?, + Operator::I64DivU => write!(f, "i64divu")?, + Operator::I64RemS => write!(f, "i64rems")?, + Operator::I64RemU => write!(f, "i64remu")?, + + Operator::F32Abs => write!(f, "f32abs")?, + Operator::F32Neg => write!(f, "f32neg")?, + Operator::F32Ceil => write!(f, "f32ceil")?, + Operator::F32Floor => write!(f, "f32floor")?, + Operator::F32Trunc => write!(f, "f32trunc")?, + Operator::F32Nearest => write!(f, "f32nearest")?, + Operator::F32Sqrt => write!(f, "f32sqrt")?, + Operator::F32Add => write!(f, "f32add")?, + Operator::F32Sub => write!(f, "f32sub")?, + Operator::F32Mul => write!(f, "f32mul")?, + Operator::F32Div => write!(f, "f32div")?, + Operator::F32Min => write!(f, "f32min")?, + Operator::F32Max => write!(f, "f32max")?, + Operator::F32Copysign => write!(f, "f32copysign")?, + + Operator::F64Abs => write!(f, "f64abs")?, + Operator::F64Neg => write!(f, "f64neg")?, + Operator::F64Ceil => write!(f, "f64ceil")?, + Operator::F64Floor => write!(f, "f64flor")?, + Operator::F64Trunc => write!(f, "f64trunc")?, + Operator::F64Nearest => write!(f, "f64nearest")?, + Operator::F64Sqrt => write!(f, "f64sqrt")?, + Operator::F64Add => write!(f, "f64add")?, + Operator::F64Sub => write!(f, "f64sub")?, + Operator::F64Mul => write!(f, "f64mul")?, + Operator::F64Div => write!(f, "f64div")?, + Operator::F64Min => write!(f, "f64min")?, + Operator::F64Max => write!(f, "f64max")?, + Operator::F64Copysign => write!(f, "f64copysign")?, + + Operator::I32WrapI64 => write!(f, "i32wrapi64")?, + Operator::I32TruncF32S => write!(f, "i32truncf32s")?, + Operator::I32TruncF32U => write!(f, "i32truncf32u")?, + Operator::I32TruncF64S => write!(f, "i32truncf64s")?, + Operator::I32TruncF64U => write!(f, "i32truncf64u")?, + Operator::I64ExtendI32S => write!(f, "i64extendi32s")?, + Operator::I64ExtendI32U => write!(f, "i64extendi32u")?, + Operator::I64TruncF32S => write!(f, "i64truncf32s")?, + Operator::I64TruncF32U => write!(f, "i64truncf32u")?, + Operator::I64TruncF64S => write!(f, "i64truncf64s")?, + Operator::I64TruncF64U => write!(f, "i64truncf64u")?, + Operator::F32ConvertI32S => write!(f, "f32converti32s")?, + Operator::F32ConvertI32U => write!(f, "f32converti32u")?, + Operator::F32ConvertI64S => write!(f, "f32converti64s")?, + Operator::F32ConvertI64U => write!(f, "f32converti64u")?, + Operator::F32DemoteF64 => write!(f, "f32demotef64")?, + Operator::F64ConvertI32S => write!(f, "f64converti32s")?, + Operator::F64ConvertI32U => write!(f, "f64converti32u")?, + Operator::F64ConvertI64S => write!(f, "f64converti64s")?, + Operator::F64ConvertI64U => write!(f, "f64converti64u")?, + Operator::F64PromoteF32 => write!(f, "f64promotef32")?, + Operator::I32Extend8S => write!(f, "i32extend8s")?, + Operator::I32Extend16S => write!(f, "i32extend16s")?, + Operator::I64Extend8S => write!(f, "i64extend8s")?, + Operator::I64Extend16S => write!(f, "i64extend16s")?, + Operator::I64Extend32S => write!(f, "i64extend32s")?, + Operator::I32TruncSatF32S => write!(f, "i32truncsatf32s")?, + Operator::I32TruncSatF32U => write!(f, "i32truncsatf32u")?, + Operator::I32TruncSatF64S => write!(f, "i32truncsatf64s")?, + Operator::I32TruncSatF64U => write!(f, "i32truncsatf64u")?, + Operator::I64TruncSatF32S => write!(f, "i64truncsatf32s")?, + Operator::I64TruncSatF32U => write!(f, "i64truncsatf32u")?, + Operator::I64TruncSatF64S => write!(f, "i64truncsatf64s")?, + Operator::I64TruncSatF64U => write!(f, "i64truncsatf64u")?, + Operator::F32ReinterpretI32 => write!(f, "f32reinterpreti32")?, + Operator::F64ReinterpretI64 => write!(f, "f64reinterpreti64")?, + Operator::I32ReinterpretF32 => write!(f, "i32reinterpretf32")?, + Operator::I64ReinterpretF64 => write!(f, "i64reinterpretf64")?, + Operator::TableGet { table_index, .. } => write!(f, "table_get<{}>", table_index)?, + Operator::TableSet { table_index, .. } => write!(f, "table_set<{}>", table_index)?, + Operator::TableGrow { table_index, .. } => write!(f, "table_grow<{}>", table_index)?, + Operator::TableSize { table_index, .. } => write!(f, "table_size<{}>", table_index)?, + Operator::MemorySize { mem } => write!(f, "memory_size<{}>", mem)?, + Operator::MemoryGrow { mem } => write!(f, "memory_grow<{}>", mem)?, + } + + Ok(()) + } +} + pub fn op_rematerialize(op: &Operator) -> bool { match op { &Operator::I32Const { .. } diff --git a/src/ops.rs b/src/ops.rs index 701159e..e6279ff 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -1,8 +1,8 @@ //! Operators. -use wasmparser::{Ieee32, Ieee64, MemoryImmediate, Type}; +use wasmparser::{Ieee32, Ieee64, MemoryImmediate}; -use crate::{Func, Global, Local, Memory, Signature, Table}; +use crate::{Func, Global, Local, Memory, Signature, Table, Type}; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct MemoryArg { @@ -11,6 +11,16 @@ pub struct MemoryArg { pub memory: Memory, } +impl std::fmt::Display for MemoryArg { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!( + f, + "{}, align={}, offset={}", + self.memory, self.align, self.offset + ) + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum Operator { Unreachable, @@ -324,7 +334,7 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator { local_index: Local::from(local_index), }), &wasmparser::Operator::Select => Ok(Operator::Select), - &wasmparser::Operator::TypedSelect { ty } => Ok(Operator::TypedSelect { ty }), + &wasmparser::Operator::TypedSelect { ty } => Ok(Operator::TypedSelect { ty: ty.into() }), &wasmparser::Operator::GlobalGet { global_index } => Ok(Operator::GlobalGet { global_index: Global::from(global_index), }),