From 726b4da33d7480ac6e95940bba7c38581d94b85a Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Fri, 24 Dec 2021 00:07:45 -0800 Subject: [PATCH] WIP. --- Cargo.toml | 2 +- src/backend/final.rs | 116 ++++++++++ src/backend/locations.rs | 207 ++++++++++++++++- src/backend/mod.rs | 4 +- src/backend/serialize.rs | 12 +- src/backend/structured.rs | 24 +- src/ops.rs | 476 ++++++++++++++++++-------------------- 7 files changed, 581 insertions(+), 260 deletions(-) create mode 100644 src/backend/final.rs diff --git a/Cargo.toml b/Cargo.toml index 13ad58e..b924ce6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] wasmparser = { git = 'https://github.com/cfallin/wasm-tools', rev = '03a81b6a6ed4d5d9730fa71bf65636a3b1538ce7' } -wasm-encoder = "0.3" +wasm-encoder = "0.8" anyhow = "1.0" structopt = "0.3" log = "0.4" diff --git a/src/backend/final.rs b/src/backend/final.rs new file mode 100644 index 0000000..c33b222 --- /dev/null +++ b/src/backend/final.rs @@ -0,0 +1,116 @@ +//! Final Wasm operator sequence production. + +use wasm_encoder::BlockType; + +use crate::{ops::ty_to_valty, FunctionBody, Operator}; + +use super::{Locations, SerializedBody, SerializedOperator}; + +#[derive(Clone, Debug)] +pub struct Wasm { + operators: Vec>, + locals: Vec, + func_types: Vec<(Vec, Vec)>, +} + +impl Wasm { + fn create_type( + &mut self, + params: Vec, + results: Vec, + ) -> u32 { + let idx = self.func_types.len() as u32; + self.func_types.push((params, results)); + idx + } + fn translate(&mut self, op: &SerializedOperator, locations: &Locations) { + match op { + SerializedOperator::StartBlock { + ref params, + ref results, + .. + } => { + let ty = self.create_type( + params.iter().map(|(ty, _)| ty_to_valty(*ty)).collect(), + results.iter().map(|ty| ty_to_valty(*ty)).collect(), + ); + self.operators + .push(wasm_encoder::Instruction::Block(BlockType::FunctionType( + ty, + ))); + } + SerializedOperator::StartLoop { + ref params, + ref results, + .. + } => { + let ty = self.create_type( + params.iter().map(|(ty, _)| ty_to_valty(*ty)).collect(), + results.iter().map(|ty| ty_to_valty(*ty)).collect(), + ); + self.operators + .push(wasm_encoder::Instruction::Loop(BlockType::FunctionType(ty))); + } + SerializedOperator::End => { + self.operators.push(wasm_encoder::Instruction::End); + } + SerializedOperator::GetArg(index) => { + self.operators + .push(wasm_encoder::Instruction::LocalGet(*index as u32)); + } + SerializedOperator::Operator(op) => { + self.operators.push(op.clone().into()); + } + SerializedOperator::Br(ref target) => { + todo!() + } + SerializedOperator::BrIf { + cond, + ref if_true, + ref if_false, + } => { + todo!() + } + SerializedOperator::BrTable { + index, + ref targets, + ref default, + } => { + todo!() + } + SerializedOperator::Get(v, i) => { + todo!() + } + SerializedOperator::Set(v, i) => { + todo!() + } + SerializedOperator::Tee(v, i) => { + todo!() + } + } + } +} + +pub fn produce_wasm(f: &FunctionBody, body: &SerializedBody, locations: &Locations) -> Wasm { + let mut wasm = Wasm { + operators: vec![], + locals: vec![], + func_types: vec![], + }; + + wasm.locals + .extend(f.locals.iter().map(|ty| ty_to_valty(*ty))); + wasm.locals + .extend(locations.new_locals.iter().map(|ty| ty_to_valty(*ty))); + + let mut next_delete = 0; + for (index, operator) in body.operators.iter().enumerate() { + if next_delete < locations.delete.len() && locations.delete[next_delete] == index { + next_delete += 1; + continue; + } + wasm.translate(operator, locations); + } + + wasm +} diff --git a/src/backend/locations.rs b/src/backend/locations.rs index 2098cbb..1bf4312 100644 --- a/src/backend/locations.rs +++ b/src/backend/locations.rs @@ -1,9 +1,208 @@ //! Location assignment (pseudo-regalloc) for SSA values onto //! locals/operand-stack values. -use crate::LocalId; +use crate::{FunctionBody, LocalId, Value}; +use fxhash::FxHashMap; -pub enum Location { - Local(LocalId), - // TODO: use operand stack +use super::{SerializedBody, SerializedOperator}; + +#[derive(Debug)] +pub struct Locations { + pub locations: FxHashMap<(Value, usize), LocalId>, + pub delete: Vec, + pub new_locals: Vec, +} + +pub struct Allocator<'a> { + locations: &'a mut Locations, + f: &'a FunctionBody, + spans: FxHashMap<(Value, usize), ValueSpan>, + starts: Vec, + ends: Vec, + freelist: FxHashMap>, +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct ValueSpan { + value: Value, + multi_value_index: usize, + /// First index in serialized body at which value is live. + start: usize, + /// First index in serialized body at which value is no longer live. + end: usize, +} + +impl ValueSpan { + fn len(&self) -> usize { + self.end - self.start + } +} + +impl Locations { + pub fn compute(f: &FunctionBody, body: &SerializedBody) -> Locations { + let mut locations = Locations { + locations: FxHashMap::default(), + delete: vec![], + new_locals: vec![], + }; + let mut allocator = Allocator { + locations: &mut locations, + f, + freelist: FxHashMap::default(), + spans: FxHashMap::default(), + starts: vec![], + ends: vec![], + }; + + allocator.compute_spans_and_deleted_ops(&body.operators[..]); + + locations + } +} + +impl<'a> Allocator<'a> { + fn handle_op(&mut self, location: usize, op: &SerializedOperator) { + let mut reads = vec![]; + let mut writes = vec![]; + op.visit_value_locals( + |value, index| { + reads.push((value, index)); + }, + |value, index| { + writes.push((value, index)); + }, + ); + + for (value, index) in reads { + let span = match self.spans.get_mut(&(value, index)) { + Some(span) => span, + None => { + panic!("Read before any write to local (v{},{})", value, index); + } + }; + span.end = location + 1; + } + + for (value, index) in writes { + self.spans + .entry((value, index)) + .or_insert(ValueSpan { + value, + multi_value_index: index, + start: location, + end: location + 1, + }) + .end = location + 1; + } + } + + fn compute_spans_and_deleted_ops(&mut self, operators: &[SerializedOperator]) { + // Delete runs of Set(A), Set(B), Get(B), Get(A): these are + // stack-neutral sequences. + let mut start = None; + let mut current_run = vec![]; + for (index, operator) in operators.iter().enumerate() { + match operator { + &SerializedOperator::Set(..) if start.is_none() => { + start = Some(index); + current_run.push(operator.clone()); + } + &SerializedOperator::Set(..) => { + current_run.push(operator.clone()); + } + &SerializedOperator::Get(v, i) + if start.is_some() + && current_run.last() == Some(&SerializedOperator::Set(v, i)) => + { + current_run.pop(); + if current_run.is_empty() { + for i in start.unwrap()..=index { + self.locations.delete.push(i); + } + start = None; + } + } + _ => { + current_run.clear(); + start = None; + } + } + } + + // For each non-deleted operator, get the reads and writes and construct spans. + let mut next_delete = 0; + for (index, operator) in operators.iter().enumerate() { + if next_delete < self.locations.delete.len() + && self.locations.delete[next_delete] == index + { + next_delete += 1; + continue; + } + + self.handle_op(index, operator); + } + + // Build lists of spans sorted by start and end. + self.starts = self.spans.values().cloned().collect(); + self.ends = self.starts.clone(); + self.starts.sort_unstable_by_key(|span| span.start); + self.ends.sort_unstable_by_key(|span| span.end); + + // Finally, assign locals to (value, index) pairs. + let mut start_idx = 0; + let mut end_idx = 0; + while start_idx < self.starts.len() || end_idx < self.ends.len() { + if start_idx < self.starts.len() && end_idx < self.ends.len() { + if self.ends[end_idx].end <= self.starts[start_idx].start { + let span = self.ends[end_idx]; + end_idx += 1; + self.handle_end(&span); + } else { + let span = self.ends[start_idx]; + start_idx += 1; + self.handle_start(&span); + } + } else if start_idx < self.starts.len() { + let span = self.ends[start_idx]; + start_idx += 1; + self.handle_start(&span); + } else { + let span = self.ends[end_idx]; + end_idx += 1; + self.handle_end(&span); + } + } + } + + fn handle_end(&mut self, span: &ValueSpan) { + let local = self + .locations + .locations + .get(&(span.value, span.multi_value_index)) + .cloned() + .unwrap(); + let ty = self.f.types[span.value.index()][span.multi_value_index]; + self.freelist + .entry(ty) + .or_insert_with(|| vec![]) + .push(local); + } + + fn handle_start(&mut self, span: &ValueSpan) { + let ty = self.f.types[span.value.index()][span.multi_value_index]; + if let Some(list) = self.freelist.get_mut(&ty) { + if let Some(local) = list.pop() { + self.locations + .locations + .insert((span.value, span.multi_value_index), local); + return; + } + } + + let new_local = self.f.locals.len() + self.locations.new_locals.len(); + self.locations.new_locals.push(ty); + self.locations + .locations + .insert((span.value, span.multi_value_index), new_local as u32); + } } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 26f7951..35482fa 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -8,6 +8,8 @@ mod schedule; pub use schedule::*; mod serialize; pub use serialize::*; - mod locations; +pub use locations::*; +mod r#final; +pub use r#final::*; diff --git a/src/backend/serialize.rs b/src/backend/serialize.rs index 4d0ae2e..802016d 100644 --- a/src/backend/serialize.rs +++ b/src/backend/serialize.rs @@ -22,21 +22,23 @@ pub struct SerializedBody { pub(crate) operators: Vec, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum SerializedBlockTarget { Fallthrough(Vec), Branch(usize, Vec), } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum SerializedOperator { StartBlock { header: BlockId, params: Vec<(wasmparser::Type, Value)>, + results: Vec, }, StartLoop { header: BlockId, params: Vec<(wasmparser::Type, Value)>, + results: Vec, }, Br(SerializedBlockTarget), BrIf { @@ -192,8 +194,8 @@ impl SerializedBody { impl<'a> SerializedBodyContext<'a> { fn compute_entry(&mut self, entry: &BlockOrderEntry) { match entry { - &BlockOrderEntry::StartBlock(header, ref params) - | &BlockOrderEntry::StartLoop(header, ref params) => { + &BlockOrderEntry::StartBlock(header, ref params, ref results) + | &BlockOrderEntry::StartLoop(header, ref params, ref results) => { let is_loop = match entry { &BlockOrderEntry::StartLoop(..) => true, _ => false, @@ -203,11 +205,13 @@ impl<'a> SerializedBodyContext<'a> { self.operators.push(SerializedOperator::StartLoop { header, params: params.clone(), + results: results.clone(), }); } else { self.operators.push(SerializedOperator::StartBlock { header, params: params.clone(), + results: results.clone(), }); } diff --git a/src/backend/structured.rs b/src/backend/structured.rs index 87c92f7..523ecfd 100644 --- a/src/backend/structured.rs +++ b/src/backend/structured.rs @@ -284,8 +284,16 @@ pub struct BlockOrder { #[derive(Clone, Debug)] pub enum BlockOrderEntry { - StartBlock(BlockId, Vec<(wasmparser::Type, Value)>), - StartLoop(BlockId, Vec<(wasmparser::Type, Value)>), + StartBlock( + BlockId, + Vec<(wasmparser::Type, Value)>, + Vec, + ), + StartLoop( + BlockId, + Vec<(wasmparser::Type, Value)>, + Vec, + ), End, BasicBlock(BlockId, Vec), } @@ -337,10 +345,18 @@ impl BlockOrder { target_stack.push(target); } let params = f.blocks[header].params.clone(); + let results = match fallthrough { + Some(fallthrough) => f.blocks[fallthrough] + .params + .iter() + .map(|(ty, _)| *ty) + .collect(), + None => vec![], + }; if is_loop { - entries.push(BlockOrderEntry::StartLoop(header, params)); + entries.push(BlockOrderEntry::StartLoop(header, params, results)); } else { - entries.push(BlockOrderEntry::StartBlock(header, params)); + entries.push(BlockOrderEntry::StartBlock(header, params, results)); } for i in 0..subregions.len() { diff --git a/src/ops.rs b/src/ops.rs index cd09666..624479d 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -468,251 +468,225 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator { } } -impl<'a> std::convert::Into> for Operator { - fn into(self) -> wasmparser::Operator<'a> { +impl<'a> std::convert::Into> for Operator { + fn into(self) -> wasm_encoder::Instruction<'static> { match &self { - &Operator::Unreachable => wasmparser::Operator::Unreachable, - &Operator::Nop => wasmparser::Operator::Nop, - &Operator::Call { function_index } => wasmparser::Operator::Call { - function_index: function_index as u32, - }, - &Operator::CallIndirect { index, table_index } => wasmparser::Operator::CallIndirect { - index: index as u32, - table_index: table_index as u32, - }, - &Operator::Return => wasmparser::Operator::Return, - &Operator::LocalSet { local_index } => wasmparser::Operator::LocalSet { local_index }, - &Operator::LocalTee { local_index } => wasmparser::Operator::LocalTee { local_index }, - &Operator::LocalGet { local_index } => wasmparser::Operator::LocalGet { local_index }, - &Operator::Select => wasmparser::Operator::Select, - &Operator::TypedSelect { ty } => wasmparser::Operator::TypedSelect { ty }, + &Operator::Unreachable => wasm_encoder::Instruction::Unreachable, + &Operator::Nop => wasm_encoder::Instruction::Nop, + &Operator::Call { function_index } => { + wasm_encoder::Instruction::Call(function_index as u32) + } + &Operator::CallIndirect { index, table_index } => { + wasm_encoder::Instruction::CallIndirect { + ty: index as u32, + table: table_index as u32, + } + } + &Operator::Return => wasm_encoder::Instruction::Return, + &Operator::LocalSet { local_index } => wasm_encoder::Instruction::LocalSet(local_index), + &Operator::LocalTee { local_index } => wasm_encoder::Instruction::LocalTee(local_index), + &Operator::LocalGet { local_index } => wasm_encoder::Instruction::LocalGet(local_index), + &Operator::Select => wasm_encoder::Instruction::Select, + &Operator::TypedSelect { ty } => { + wasm_encoder::Instruction::TypedSelect(ty_to_valty(ty)) + } &Operator::GlobalGet { global_index } => { - wasmparser::Operator::GlobalGet { global_index } + wasm_encoder::Instruction::GlobalGet(global_index) } &Operator::GlobalSet { global_index } => { - wasmparser::Operator::GlobalSet { global_index } + wasm_encoder::Instruction::GlobalSet(global_index) } - &Operator::I32Load { memory } => wasmparser::Operator::I32Load { - memarg: memory.into(), - }, - &Operator::I64Load { memory } => wasmparser::Operator::I64Load { - memarg: memory.into(), - }, - &Operator::F32Load { memory } => wasmparser::Operator::F32Load { - memarg: memory.into(), - }, - &Operator::F64Load { memory } => wasmparser::Operator::F64Load { - memarg: memory.into(), - }, - &Operator::I32Load8S { memory } => wasmparser::Operator::I32Load8S { - memarg: memory.into(), - }, - &Operator::I32Load8U { memory } => wasmparser::Operator::I32Load8U { - memarg: memory.into(), - }, - &Operator::I32Load16S { memory } => wasmparser::Operator::I32Load16S { - memarg: memory.into(), - }, - &Operator::I32Load16U { memory } => wasmparser::Operator::I32Load16U { - memarg: memory.into(), - }, - &Operator::I64Load8S { memory } => wasmparser::Operator::I64Load8S { - memarg: memory.into(), - }, - &Operator::I64Load8U { memory } => wasmparser::Operator::I64Load8U { - memarg: memory.into(), - }, - &Operator::I64Load16S { memory } => wasmparser::Operator::I64Load16S { - memarg: memory.into(), - }, - &Operator::I64Load16U { memory } => wasmparser::Operator::I64Load16U { - memarg: memory.into(), - }, - &Operator::I64Load32S { memory } => wasmparser::Operator::I64Load32S { - memarg: memory.into(), - }, - &Operator::I64Load32U { memory } => wasmparser::Operator::I64Load32U { - memarg: memory.into(), - }, - &Operator::I32Store { memory } => wasmparser::Operator::I32Store { - memarg: memory.into(), - }, - &Operator::I64Store { memory } => wasmparser::Operator::I64Store { - memarg: memory.into(), - }, - &Operator::F32Store { memory } => wasmparser::Operator::F32Store { - memarg: memory.into(), - }, - &Operator::F64Store { memory } => wasmparser::Operator::F64Store { - memarg: memory.into(), - }, - &Operator::I32Store8 { memory } => wasmparser::Operator::I32Store8 { - memarg: memory.into(), - }, - &Operator::I32Store16 { memory } => wasmparser::Operator::I32Store16 { - memarg: memory.into(), - }, - &Operator::I64Store8 { memory } => wasmparser::Operator::I64Store8 { - memarg: memory.into(), - }, - &Operator::I64Store16 { memory } => wasmparser::Operator::I64Store16 { - memarg: memory.into(), - }, - &Operator::I64Store32 { memory } => wasmparser::Operator::I64Store32 { - memarg: memory.into(), - }, - &Operator::I32Const { value } => wasmparser::Operator::I32Const { value }, - &Operator::I64Const { value } => wasmparser::Operator::I64Const { value }, - &Operator::F32Const { value } => wasmparser::Operator::F32Const { value }, - &Operator::F64Const { value } => wasmparser::Operator::F64Const { value }, - &Operator::I32Eqz => wasmparser::Operator::I32Eqz, - &Operator::I32Eq => wasmparser::Operator::I32Eq, - &Operator::I32Ne => wasmparser::Operator::I32Ne, - &Operator::I32LtS => wasmparser::Operator::I32LtS, - &Operator::I32LtU => wasmparser::Operator::I32LtU, - &Operator::I32GtS => wasmparser::Operator::I32GtS, - &Operator::I32GtU => wasmparser::Operator::I32GtU, - &Operator::I32LeS => wasmparser::Operator::I32LeS, - &Operator::I32LeU => wasmparser::Operator::I32LeU, - &Operator::I32GeS => wasmparser::Operator::I32GeS, - &Operator::I32GeU => wasmparser::Operator::I32GeU, - &Operator::I64Eqz => wasmparser::Operator::I64Eqz, - &Operator::I64Eq => wasmparser::Operator::I64Eq, - &Operator::I64Ne => wasmparser::Operator::I64Ne, - &Operator::I64LtS => wasmparser::Operator::I64LtS, - &Operator::I64LtU => wasmparser::Operator::I64LtU, - &Operator::I64GtU => wasmparser::Operator::I64GtU, - &Operator::I64GtS => wasmparser::Operator::I64GtS, - &Operator::I64LeS => wasmparser::Operator::I64LeS, - &Operator::I64LeU => wasmparser::Operator::I64LeU, - &Operator::I64GeS => wasmparser::Operator::I64GeS, - &Operator::I64GeU => wasmparser::Operator::I64GeU, - &Operator::F32Eq => wasmparser::Operator::F32Eq, - &Operator::F32Ne => wasmparser::Operator::F32Ne, - &Operator::F32Lt => wasmparser::Operator::F32Lt, - &Operator::F32Gt => wasmparser::Operator::F32Gt, - &Operator::F32Le => wasmparser::Operator::F32Le, - &Operator::F32Ge => wasmparser::Operator::F32Ge, - &Operator::F64Eq => wasmparser::Operator::F64Eq, - &Operator::F64Ne => wasmparser::Operator::F64Ne, - &Operator::F64Lt => wasmparser::Operator::F64Lt, - &Operator::F64Gt => wasmparser::Operator::F64Gt, - &Operator::F64Le => wasmparser::Operator::F64Le, - &Operator::F64Ge => wasmparser::Operator::F64Ge, - &Operator::I32Clz => wasmparser::Operator::I32Clz, - &Operator::I32Ctz => wasmparser::Operator::I32Ctz, - &Operator::I32Popcnt => wasmparser::Operator::I32Popcnt, - &Operator::I32Add => wasmparser::Operator::I32Add, - &Operator::I32Sub => wasmparser::Operator::I32Sub, - &Operator::I32Mul => wasmparser::Operator::I32Mul, - &Operator::I32DivS => wasmparser::Operator::I32DivS, - &Operator::I32DivU => wasmparser::Operator::I32DivU, - &Operator::I32RemS => wasmparser::Operator::I32RemS, - &Operator::I32RemU => wasmparser::Operator::I32RemU, - &Operator::I32And => wasmparser::Operator::I32And, - &Operator::I32Or => wasmparser::Operator::I32Or, - &Operator::I32Xor => wasmparser::Operator::I32Xor, - &Operator::I32Shl => wasmparser::Operator::I32Shl, - &Operator::I32ShrS => wasmparser::Operator::I32ShrS, - &Operator::I32ShrU => wasmparser::Operator::I32ShrU, - &Operator::I32Rotl => wasmparser::Operator::I32Rotl, - &Operator::I32Rotr => wasmparser::Operator::I32Rotr, - &Operator::I64Clz => wasmparser::Operator::I64Clz, - &Operator::I64Ctz => wasmparser::Operator::I64Ctz, - &Operator::I64Popcnt => wasmparser::Operator::I64Popcnt, - &Operator::I64Add => wasmparser::Operator::I64Add, - &Operator::I64Sub => wasmparser::Operator::I64Sub, - &Operator::I64Mul => wasmparser::Operator::I64Mul, - &Operator::I64DivS => wasmparser::Operator::I64DivS, - &Operator::I64DivU => wasmparser::Operator::I64DivU, - &Operator::I64RemS => wasmparser::Operator::I64RemS, - &Operator::I64RemU => wasmparser::Operator::I64RemU, - &Operator::I64And => wasmparser::Operator::I64And, - &Operator::I64Or => wasmparser::Operator::I64Or, - &Operator::I64Xor => wasmparser::Operator::I64Xor, - &Operator::I64Shl => wasmparser::Operator::I64Shl, - &Operator::I64ShrS => wasmparser::Operator::I64ShrS, - &Operator::I64ShrU => wasmparser::Operator::I64ShrU, - &Operator::I64Rotl => wasmparser::Operator::I64Rotl, - &Operator::I64Rotr => wasmparser::Operator::I64Rotr, - &Operator::F32Abs => wasmparser::Operator::F32Abs, - &Operator::F32Neg => wasmparser::Operator::F32Neg, - &Operator::F32Ceil => wasmparser::Operator::F32Ceil, - &Operator::F32Floor => wasmparser::Operator::F32Floor, - &Operator::F32Trunc => wasmparser::Operator::F32Trunc, - &Operator::F32Nearest => wasmparser::Operator::F32Nearest, - &Operator::F32Sqrt => wasmparser::Operator::F32Sqrt, - &Operator::F32Add => wasmparser::Operator::F32Add, - &Operator::F32Sub => wasmparser::Operator::F32Sub, - &Operator::F32Mul => wasmparser::Operator::F32Mul, - &Operator::F32Div => wasmparser::Operator::F32Div, - &Operator::F32Min => wasmparser::Operator::F32Min, - &Operator::F32Max => wasmparser::Operator::F32Max, - &Operator::F32Copysign => wasmparser::Operator::F32Copysign, - &Operator::F64Abs => wasmparser::Operator::F64Abs, - &Operator::F64Neg => wasmparser::Operator::F64Neg, - &Operator::F64Ceil => wasmparser::Operator::F64Ceil, - &Operator::F64Floor => wasmparser::Operator::F64Floor, - &Operator::F64Trunc => wasmparser::Operator::F64Trunc, - &Operator::F64Nearest => wasmparser::Operator::F64Nearest, - &Operator::F64Sqrt => wasmparser::Operator::F64Sqrt, - &Operator::F64Add => wasmparser::Operator::F64Add, - &Operator::F64Sub => wasmparser::Operator::F64Sub, - &Operator::F64Mul => wasmparser::Operator::F64Mul, - &Operator::F64Div => wasmparser::Operator::F64Div, - &Operator::F64Min => wasmparser::Operator::F64Min, - &Operator::F64Max => wasmparser::Operator::F64Max, - &Operator::F64Copysign => wasmparser::Operator::F64Copysign, - &Operator::I32WrapI64 => wasmparser::Operator::I32WrapI64, - &Operator::I32TruncF32S => wasmparser::Operator::I32TruncF32S, - &Operator::I32TruncF32U => wasmparser::Operator::I32TruncF32U, - &Operator::I32TruncF64S => wasmparser::Operator::I32TruncF64S, - &Operator::I32TruncF64U => wasmparser::Operator::I32TruncF64U, - &Operator::I64ExtendI32S => wasmparser::Operator::I64ExtendI32S, - &Operator::I64ExtendI32U => wasmparser::Operator::I64ExtendI32U, - &Operator::I64TruncF32S => wasmparser::Operator::I64TruncF32S, - &Operator::I64TruncF32U => wasmparser::Operator::I64TruncF32U, - &Operator::I64TruncF64S => wasmparser::Operator::I64TruncF64S, - &Operator::I64TruncF64U => wasmparser::Operator::I64TruncF64U, - &Operator::F32ConvertI32S => wasmparser::Operator::F32ConvertI32S, - &Operator::F32ConvertI32U => wasmparser::Operator::F32ConvertI32U, - &Operator::F32ConvertI64S => wasmparser::Operator::F32ConvertI64S, - &Operator::F32ConvertI64U => wasmparser::Operator::F32ConvertI64U, - &Operator::F32DemoteF64 => wasmparser::Operator::F32DemoteF64, - &Operator::F64ConvertI32S => wasmparser::Operator::F64ConvertI32S, - &Operator::F64ConvertI32U => wasmparser::Operator::F64ConvertI32U, - &Operator::F64ConvertI64S => wasmparser::Operator::F64ConvertI64S, - &Operator::F64ConvertI64U => wasmparser::Operator::F64ConvertI64U, - &Operator::F64PromoteF32 => wasmparser::Operator::F64PromoteF32, - &Operator::I32Extend8S => wasmparser::Operator::I32Extend8S, - &Operator::I32Extend16S => wasmparser::Operator::I32Extend16S, - &Operator::I64Extend8S => wasmparser::Operator::I64Extend8S, - &Operator::I64Extend16S => wasmparser::Operator::I64Extend16S, - &Operator::I64Extend32S => wasmparser::Operator::I64Extend32S, - &Operator::I32TruncSatF32S => wasmparser::Operator::I32TruncSatF32S, - &Operator::I32TruncSatF32U => wasmparser::Operator::I32TruncSatF32U, - &Operator::I32TruncSatF64S => wasmparser::Operator::I32TruncSatF64S, - &Operator::I32TruncSatF64U => wasmparser::Operator::I32TruncSatF64U, - &Operator::I64TruncSatF32S => wasmparser::Operator::I64TruncSatF32S, - &Operator::I64TruncSatF32U => wasmparser::Operator::I64TruncSatF32U, - &Operator::I64TruncSatF64S => wasmparser::Operator::I64TruncSatF64S, - &Operator::I64TruncSatF64U => wasmparser::Operator::I64TruncSatF64U, - &Operator::F32ReinterpretI32 => wasmparser::Operator::F32ReinterpretI32, - &Operator::F64ReinterpretI64 => wasmparser::Operator::F64ReinterpretI64, - &Operator::I32ReinterpretF32 => wasmparser::Operator::I32ReinterpretF32, - &Operator::I64ReinterpretF64 => wasmparser::Operator::I64ReinterpretF64, - &Operator::TableGet { table } => wasmparser::Operator::TableGet { table }, - &Operator::TableSet { table } => wasmparser::Operator::TableSet { table }, - &Operator::TableGrow { table } => wasmparser::Operator::TableGrow { table }, - &Operator::TableSize { table } => wasmparser::Operator::TableSize { table }, - &Operator::MemorySize { mem } => wasmparser::Operator::MemorySize { - mem, - mem_byte: mem as u8, - }, - &Operator::MemoryGrow { mem } => wasmparser::Operator::MemoryGrow { - mem, - mem_byte: mem as u8, - }, + &Operator::I32Load { memory } => wasm_encoder::Instruction::I32Load(memory.into()), + &Operator::I64Load { memory } => wasm_encoder::Instruction::I64Load(memory.into()), + &Operator::F32Load { memory } => wasm_encoder::Instruction::F32Load(memory.into()), + &Operator::F64Load { memory } => wasm_encoder::Instruction::F64Load(memory.into()), + &Operator::I32Load8S { memory } => wasm_encoder::Instruction::I32Load8_S(memory.into()), + &Operator::I32Load8U { memory } => wasm_encoder::Instruction::I32Load8_U(memory.into()), + &Operator::I32Load16S { memory } => { + wasm_encoder::Instruction::I32Load16_S(memory.into()) + } + &Operator::I32Load16U { memory } => { + wasm_encoder::Instruction::I32Load16_U(memory.into()) + } + &Operator::I64Load8S { memory } => wasm_encoder::Instruction::I64Load8_S(memory.into()), + &Operator::I64Load8U { memory } => wasm_encoder::Instruction::I64Load8_U(memory.into()), + &Operator::I64Load16S { memory } => { + wasm_encoder::Instruction::I64Load16_S(memory.into()) + } + &Operator::I64Load16U { memory } => { + wasm_encoder::Instruction::I64Load16_U(memory.into()) + } + &Operator::I64Load32S { memory } => { + wasm_encoder::Instruction::I64Load32_S(memory.into()) + } + &Operator::I64Load32U { memory } => { + wasm_encoder::Instruction::I64Load32_U(memory.into()) + } + &Operator::I32Store { memory } => wasm_encoder::Instruction::I32Store(memory.into()), + &Operator::I64Store { memory } => wasm_encoder::Instruction::I64Store(memory.into()), + &Operator::F32Store { memory } => wasm_encoder::Instruction::F32Store(memory.into()), + &Operator::F64Store { memory } => wasm_encoder::Instruction::F64Store(memory.into()), + &Operator::I32Store8 { memory } => wasm_encoder::Instruction::I32Store8(memory.into()), + &Operator::I32Store16 { memory } => { + wasm_encoder::Instruction::I32Store16(memory.into()) + } + &Operator::I64Store8 { memory } => wasm_encoder::Instruction::I64Store8(memory.into()), + &Operator::I64Store16 { memory } => { + wasm_encoder::Instruction::I64Store16(memory.into()) + } + &Operator::I64Store32 { memory } => { + wasm_encoder::Instruction::I64Store32(memory.into()) + } + &Operator::I32Const { value } => wasm_encoder::Instruction::I32Const(value), + &Operator::I64Const { value } => wasm_encoder::Instruction::I64Const(value), + &Operator::F32Const { value } => { + wasm_encoder::Instruction::F32Const(f32::from_bits(value.bits())) + } + &Operator::F64Const { value } => { + wasm_encoder::Instruction::F64Const(f64::from_bits(value.bits())) + } + &Operator::I32Eqz => wasm_encoder::Instruction::I32Eqz, + &Operator::I32Eq => wasm_encoder::Instruction::I32Eq, + &Operator::I32Ne => wasm_encoder::Instruction::I32Neq, + &Operator::I32LtS => wasm_encoder::Instruction::I32LtS, + &Operator::I32LtU => wasm_encoder::Instruction::I32LtU, + &Operator::I32GtS => wasm_encoder::Instruction::I32GtS, + &Operator::I32GtU => wasm_encoder::Instruction::I32GtU, + &Operator::I32LeS => wasm_encoder::Instruction::I32LeS, + &Operator::I32LeU => wasm_encoder::Instruction::I32LeU, + &Operator::I32GeS => wasm_encoder::Instruction::I32GeS, + &Operator::I32GeU => wasm_encoder::Instruction::I32GeU, + &Operator::I64Eqz => wasm_encoder::Instruction::I64Eqz, + &Operator::I64Eq => wasm_encoder::Instruction::I64Eq, + &Operator::I64Ne => wasm_encoder::Instruction::I64Neq, + &Operator::I64LtS => wasm_encoder::Instruction::I64LtS, + &Operator::I64LtU => wasm_encoder::Instruction::I64LtU, + &Operator::I64GtU => wasm_encoder::Instruction::I64GtU, + &Operator::I64GtS => wasm_encoder::Instruction::I64GtS, + &Operator::I64LeS => wasm_encoder::Instruction::I64LeS, + &Operator::I64LeU => wasm_encoder::Instruction::I64LeU, + &Operator::I64GeS => wasm_encoder::Instruction::I64GeS, + &Operator::I64GeU => wasm_encoder::Instruction::I64GeU, + &Operator::F32Eq => wasm_encoder::Instruction::F32Eq, + &Operator::F32Ne => wasm_encoder::Instruction::F32Neq, + &Operator::F32Lt => wasm_encoder::Instruction::F32Lt, + &Operator::F32Gt => wasm_encoder::Instruction::F32Gt, + &Operator::F32Le => wasm_encoder::Instruction::F32Le, + &Operator::F32Ge => wasm_encoder::Instruction::F32Ge, + &Operator::F64Eq => wasm_encoder::Instruction::F64Eq, + &Operator::F64Ne => wasm_encoder::Instruction::F64Neq, + &Operator::F64Lt => wasm_encoder::Instruction::F64Lt, + &Operator::F64Gt => wasm_encoder::Instruction::F64Gt, + &Operator::F64Le => wasm_encoder::Instruction::F64Le, + &Operator::F64Ge => wasm_encoder::Instruction::F64Ge, + &Operator::I32Clz => wasm_encoder::Instruction::I32Clz, + &Operator::I32Ctz => wasm_encoder::Instruction::I32Ctz, + &Operator::I32Popcnt => wasm_encoder::Instruction::I32Popcnt, + &Operator::I32Add => wasm_encoder::Instruction::I32Add, + &Operator::I32Sub => wasm_encoder::Instruction::I32Sub, + &Operator::I32Mul => wasm_encoder::Instruction::I32Mul, + &Operator::I32DivS => wasm_encoder::Instruction::I32DivS, + &Operator::I32DivU => wasm_encoder::Instruction::I32DivU, + &Operator::I32RemS => wasm_encoder::Instruction::I32RemS, + &Operator::I32RemU => wasm_encoder::Instruction::I32RemU, + &Operator::I32And => wasm_encoder::Instruction::I32And, + &Operator::I32Or => wasm_encoder::Instruction::I32Or, + &Operator::I32Xor => wasm_encoder::Instruction::I32Xor, + &Operator::I32Shl => wasm_encoder::Instruction::I32Shl, + &Operator::I32ShrS => wasm_encoder::Instruction::I32ShrS, + &Operator::I32ShrU => wasm_encoder::Instruction::I32ShrU, + &Operator::I32Rotl => wasm_encoder::Instruction::I32Rotl, + &Operator::I32Rotr => wasm_encoder::Instruction::I32Rotr, + &Operator::I64Clz => wasm_encoder::Instruction::I64Clz, + &Operator::I64Ctz => wasm_encoder::Instruction::I64Ctz, + &Operator::I64Popcnt => wasm_encoder::Instruction::I64Popcnt, + &Operator::I64Add => wasm_encoder::Instruction::I64Add, + &Operator::I64Sub => wasm_encoder::Instruction::I64Sub, + &Operator::I64Mul => wasm_encoder::Instruction::I64Mul, + &Operator::I64DivS => wasm_encoder::Instruction::I64DivS, + &Operator::I64DivU => wasm_encoder::Instruction::I64DivU, + &Operator::I64RemS => wasm_encoder::Instruction::I64RemS, + &Operator::I64RemU => wasm_encoder::Instruction::I64RemU, + &Operator::I64And => wasm_encoder::Instruction::I64And, + &Operator::I64Or => wasm_encoder::Instruction::I64Or, + &Operator::I64Xor => wasm_encoder::Instruction::I64Xor, + &Operator::I64Shl => wasm_encoder::Instruction::I64Shl, + &Operator::I64ShrS => wasm_encoder::Instruction::I64ShrS, + &Operator::I64ShrU => wasm_encoder::Instruction::I64ShrU, + &Operator::I64Rotl => wasm_encoder::Instruction::I64Rotl, + &Operator::I64Rotr => wasm_encoder::Instruction::I64Rotr, + &Operator::F32Abs => wasm_encoder::Instruction::F32Abs, + &Operator::F32Neg => wasm_encoder::Instruction::F32Neg, + &Operator::F32Ceil => wasm_encoder::Instruction::F32Ceil, + &Operator::F32Floor => wasm_encoder::Instruction::F32Floor, + &Operator::F32Trunc => wasm_encoder::Instruction::F32Trunc, + &Operator::F32Nearest => wasm_encoder::Instruction::F32Nearest, + &Operator::F32Sqrt => wasm_encoder::Instruction::F32Sqrt, + &Operator::F32Add => wasm_encoder::Instruction::F32Add, + &Operator::F32Sub => wasm_encoder::Instruction::F32Sub, + &Operator::F32Mul => wasm_encoder::Instruction::F32Mul, + &Operator::F32Div => wasm_encoder::Instruction::F32Div, + &Operator::F32Min => wasm_encoder::Instruction::F32Min, + &Operator::F32Max => wasm_encoder::Instruction::F32Max, + &Operator::F32Copysign => wasm_encoder::Instruction::F32Copysign, + &Operator::F64Abs => wasm_encoder::Instruction::F64Abs, + &Operator::F64Neg => wasm_encoder::Instruction::F64Neg, + &Operator::F64Ceil => wasm_encoder::Instruction::F64Ceil, + &Operator::F64Floor => wasm_encoder::Instruction::F64Floor, + &Operator::F64Trunc => wasm_encoder::Instruction::F64Trunc, + &Operator::F64Nearest => wasm_encoder::Instruction::F64Nearest, + &Operator::F64Sqrt => wasm_encoder::Instruction::F64Sqrt, + &Operator::F64Add => wasm_encoder::Instruction::F64Add, + &Operator::F64Sub => wasm_encoder::Instruction::F64Sub, + &Operator::F64Mul => wasm_encoder::Instruction::F64Mul, + &Operator::F64Div => wasm_encoder::Instruction::F64Div, + &Operator::F64Min => wasm_encoder::Instruction::F64Min, + &Operator::F64Max => wasm_encoder::Instruction::F64Max, + &Operator::F64Copysign => wasm_encoder::Instruction::F64Copysign, + &Operator::I32WrapI64 => wasm_encoder::Instruction::I32WrapI64, + &Operator::I32TruncF32S => wasm_encoder::Instruction::I32TruncF32S, + &Operator::I32TruncF32U => wasm_encoder::Instruction::I32TruncF32U, + &Operator::I32TruncF64S => wasm_encoder::Instruction::I32TruncF64S, + &Operator::I32TruncF64U => wasm_encoder::Instruction::I32TruncF64U, + &Operator::I64ExtendI32S => wasm_encoder::Instruction::I64ExtendI32S, + &Operator::I64ExtendI32U => wasm_encoder::Instruction::I64ExtendI32U, + &Operator::I64TruncF32S => wasm_encoder::Instruction::I64TruncF32S, + &Operator::I64TruncF32U => wasm_encoder::Instruction::I64TruncF32U, + &Operator::I64TruncF64S => wasm_encoder::Instruction::I64TruncF64S, + &Operator::I64TruncF64U => wasm_encoder::Instruction::I64TruncF64U, + &Operator::F32ConvertI32S => wasm_encoder::Instruction::F32ConvertI32S, + &Operator::F32ConvertI32U => wasm_encoder::Instruction::F32ConvertI32U, + &Operator::F32ConvertI64S => wasm_encoder::Instruction::F32ConvertI64S, + &Operator::F32ConvertI64U => wasm_encoder::Instruction::F32ConvertI64U, + &Operator::F32DemoteF64 => wasm_encoder::Instruction::F32DemoteF64, + &Operator::F64ConvertI32S => wasm_encoder::Instruction::F64ConvertI32S, + &Operator::F64ConvertI32U => wasm_encoder::Instruction::F64ConvertI32U, + &Operator::F64ConvertI64S => wasm_encoder::Instruction::F64ConvertI64S, + &Operator::F64ConvertI64U => wasm_encoder::Instruction::F64ConvertI64U, + &Operator::F64PromoteF32 => wasm_encoder::Instruction::F64PromoteF32, + &Operator::I32Extend8S => wasm_encoder::Instruction::I32Extend8S, + &Operator::I32Extend16S => wasm_encoder::Instruction::I32Extend16S, + &Operator::I64Extend8S => wasm_encoder::Instruction::I64Extend8S, + &Operator::I64Extend16S => wasm_encoder::Instruction::I64Extend16S, + &Operator::I64Extend32S => wasm_encoder::Instruction::I64Extend32S, + &Operator::I32TruncSatF32S => wasm_encoder::Instruction::I32TruncSatF32S, + &Operator::I32TruncSatF32U => wasm_encoder::Instruction::I32TruncSatF32U, + &Operator::I32TruncSatF64S => wasm_encoder::Instruction::I32TruncSatF64S, + &Operator::I32TruncSatF64U => wasm_encoder::Instruction::I32TruncSatF64U, + &Operator::I64TruncSatF32S => wasm_encoder::Instruction::I64TruncSatF32S, + &Operator::I64TruncSatF32U => wasm_encoder::Instruction::I64TruncSatF32U, + &Operator::I64TruncSatF64S => wasm_encoder::Instruction::I64TruncSatF64S, + &Operator::I64TruncSatF64U => wasm_encoder::Instruction::I64TruncSatF64U, + &Operator::F32ReinterpretI32 => wasm_encoder::Instruction::F32ReinterpretI32, + &Operator::F64ReinterpretI64 => wasm_encoder::Instruction::F64ReinterpretI64, + &Operator::I32ReinterpretF32 => wasm_encoder::Instruction::I32ReinterpretF32, + &Operator::I64ReinterpretF64 => wasm_encoder::Instruction::I64ReinterpretF64, + &Operator::TableGet { table } => wasm_encoder::Instruction::TableGet { table }, + &Operator::TableSet { table } => wasm_encoder::Instruction::TableSet { table }, + &Operator::TableGrow { table } => wasm_encoder::Instruction::TableGrow { table }, + &Operator::TableSize { table } => wasm_encoder::Instruction::TableSize { table }, + &Operator::MemorySize { mem } => wasm_encoder::Instruction::MemorySize(mem), + &Operator::MemoryGrow { mem } => wasm_encoder::Instruction::MemoryGrow(mem), } } } @@ -727,12 +701,22 @@ impl std::convert::From for Memory { } } -impl std::convert::Into for Memory { - fn into(self) -> MemoryImmediate { - MemoryImmediate { - align: self.align, - offset: self.offset, - memory: self.memory as u32, +impl std::convert::Into for Memory { + fn into(self) -> wasm_encoder::MemArg { + wasm_encoder::MemArg { + align: self.align as u32, + offset: self.offset as u64, + memory_index: self.memory as u32, } } } + +pub fn ty_to_valty(ty: Type) -> wasm_encoder::ValType { + match ty { + Type::I32 => wasm_encoder::ValType::I32, + Type::I64 => wasm_encoder::ValType::I64, + Type::F32 => wasm_encoder::ValType::F32, + Type::F64 => wasm_encoder::ValType::F64, + _ => panic!("Unsupported type: {:?}", ty), + } +}