This commit is contained in:
Chris Fallin 2021-12-24 00:07:45 -08:00
parent 635befa210
commit 726b4da33d
7 changed files with 581 additions and 260 deletions

View file

@ -8,7 +8,7 @@ edition = "2018"
[dependencies] [dependencies]
wasmparser = { git = 'https://github.com/cfallin/wasm-tools', rev = '03a81b6a6ed4d5d9730fa71bf65636a3b1538ce7' } wasmparser = { git = 'https://github.com/cfallin/wasm-tools', rev = '03a81b6a6ed4d5d9730fa71bf65636a3b1538ce7' }
wasm-encoder = "0.3" wasm-encoder = "0.8"
anyhow = "1.0" anyhow = "1.0"
structopt = "0.3" structopt = "0.3"
log = "0.4" log = "0.4"

116
src/backend/final.rs Normal file
View file

@ -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<wasm_encoder::Instruction<'static>>,
locals: Vec<wasm_encoder::ValType>,
func_types: Vec<(Vec<wasm_encoder::ValType>, Vec<wasm_encoder::ValType>)>,
}
impl Wasm {
fn create_type(
&mut self,
params: Vec<wasm_encoder::ValType>,
results: Vec<wasm_encoder::ValType>,
) -> 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
}

View file

@ -1,9 +1,208 @@
//! Location assignment (pseudo-regalloc) for SSA values onto //! Location assignment (pseudo-regalloc) for SSA values onto
//! locals/operand-stack values. //! locals/operand-stack values.
use crate::LocalId; use crate::{FunctionBody, LocalId, Value};
use fxhash::FxHashMap;
pub enum Location { use super::{SerializedBody, SerializedOperator};
Local(LocalId),
// TODO: use operand stack #[derive(Debug)]
pub struct Locations {
pub locations: FxHashMap<(Value, usize), LocalId>,
pub delete: Vec<usize>,
pub new_locals: Vec<wasmparser::Type>,
}
pub struct Allocator<'a> {
locations: &'a mut Locations,
f: &'a FunctionBody,
spans: FxHashMap<(Value, usize), ValueSpan>,
starts: Vec<ValueSpan>,
ends: Vec<ValueSpan>,
freelist: FxHashMap<wasmparser::Type, Vec<LocalId>>,
}
#[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);
}
} }

View file

@ -8,6 +8,8 @@ mod schedule;
pub use schedule::*; pub use schedule::*;
mod serialize; mod serialize;
pub use serialize::*; pub use serialize::*;
mod locations; mod locations;
pub use locations::*;
mod r#final;
pub use r#final::*;

View file

@ -22,21 +22,23 @@ pub struct SerializedBody {
pub(crate) operators: Vec<SerializedOperator>, pub(crate) operators: Vec<SerializedOperator>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum SerializedBlockTarget { pub enum SerializedBlockTarget {
Fallthrough(Vec<SerializedOperator>), Fallthrough(Vec<SerializedOperator>),
Branch(usize, Vec<SerializedOperator>), Branch(usize, Vec<SerializedOperator>),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum SerializedOperator { pub enum SerializedOperator {
StartBlock { StartBlock {
header: BlockId, header: BlockId,
params: Vec<(wasmparser::Type, Value)>, params: Vec<(wasmparser::Type, Value)>,
results: Vec<wasmparser::Type>,
}, },
StartLoop { StartLoop {
header: BlockId, header: BlockId,
params: Vec<(wasmparser::Type, Value)>, params: Vec<(wasmparser::Type, Value)>,
results: Vec<wasmparser::Type>,
}, },
Br(SerializedBlockTarget), Br(SerializedBlockTarget),
BrIf { BrIf {
@ -192,8 +194,8 @@ impl SerializedBody {
impl<'a> SerializedBodyContext<'a> { impl<'a> SerializedBodyContext<'a> {
fn compute_entry(&mut self, entry: &BlockOrderEntry) { fn compute_entry(&mut self, entry: &BlockOrderEntry) {
match entry { match entry {
&BlockOrderEntry::StartBlock(header, ref params) &BlockOrderEntry::StartBlock(header, ref params, ref results)
| &BlockOrderEntry::StartLoop(header, ref params) => { | &BlockOrderEntry::StartLoop(header, ref params, ref results) => {
let is_loop = match entry { let is_loop = match entry {
&BlockOrderEntry::StartLoop(..) => true, &BlockOrderEntry::StartLoop(..) => true,
_ => false, _ => false,
@ -203,11 +205,13 @@ impl<'a> SerializedBodyContext<'a> {
self.operators.push(SerializedOperator::StartLoop { self.operators.push(SerializedOperator::StartLoop {
header, header,
params: params.clone(), params: params.clone(),
results: results.clone(),
}); });
} else { } else {
self.operators.push(SerializedOperator::StartBlock { self.operators.push(SerializedOperator::StartBlock {
header, header,
params: params.clone(), params: params.clone(),
results: results.clone(),
}); });
} }

View file

@ -284,8 +284,16 @@ pub struct BlockOrder {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum BlockOrderEntry { pub enum BlockOrderEntry {
StartBlock(BlockId, Vec<(wasmparser::Type, Value)>), StartBlock(
StartLoop(BlockId, Vec<(wasmparser::Type, Value)>), BlockId,
Vec<(wasmparser::Type, Value)>,
Vec<wasmparser::Type>,
),
StartLoop(
BlockId,
Vec<(wasmparser::Type, Value)>,
Vec<wasmparser::Type>,
),
End, End,
BasicBlock(BlockId, Vec<BlockOrderTarget>), BasicBlock(BlockId, Vec<BlockOrderTarget>),
} }
@ -337,10 +345,18 @@ impl BlockOrder {
target_stack.push(target); target_stack.push(target);
} }
let params = f.blocks[header].params.clone(); 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 { if is_loop {
entries.push(BlockOrderEntry::StartLoop(header, params)); entries.push(BlockOrderEntry::StartLoop(header, params, results));
} else { } else {
entries.push(BlockOrderEntry::StartBlock(header, params)); entries.push(BlockOrderEntry::StartBlock(header, params, results));
} }
for i in 0..subregions.len() { for i in 0..subregions.len() {

View file

@ -468,251 +468,225 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator {
} }
} }
impl<'a> std::convert::Into<wasmparser::Operator<'a>> for Operator { impl<'a> std::convert::Into<wasm_encoder::Instruction<'static>> for Operator {
fn into(self) -> wasmparser::Operator<'a> { fn into(self) -> wasm_encoder::Instruction<'static> {
match &self { match &self {
&Operator::Unreachable => wasmparser::Operator::Unreachable, &Operator::Unreachable => wasm_encoder::Instruction::Unreachable,
&Operator::Nop => wasmparser::Operator::Nop, &Operator::Nop => wasm_encoder::Instruction::Nop,
&Operator::Call { function_index } => wasmparser::Operator::Call { &Operator::Call { function_index } => {
function_index: function_index as u32, wasm_encoder::Instruction::Call(function_index as u32)
}, }
&Operator::CallIndirect { index, table_index } => wasmparser::Operator::CallIndirect { &Operator::CallIndirect { index, table_index } => {
index: index as u32, wasm_encoder::Instruction::CallIndirect {
table_index: table_index as u32, ty: index as u32,
}, table: 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::Return => wasm_encoder::Instruction::Return,
&Operator::LocalGet { local_index } => wasmparser::Operator::LocalGet { local_index }, &Operator::LocalSet { local_index } => wasm_encoder::Instruction::LocalSet(local_index),
&Operator::Select => wasmparser::Operator::Select, &Operator::LocalTee { local_index } => wasm_encoder::Instruction::LocalTee(local_index),
&Operator::TypedSelect { ty } => wasmparser::Operator::TypedSelect { ty }, &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 } => { &Operator::GlobalGet { global_index } => {
wasmparser::Operator::GlobalGet { global_index } wasm_encoder::Instruction::GlobalGet(global_index)
} }
&Operator::GlobalSet { global_index } => { &Operator::GlobalSet { global_index } => {
wasmparser::Operator::GlobalSet { global_index } wasm_encoder::Instruction::GlobalSet(global_index)
} }
&Operator::I32Load { memory } => wasmparser::Operator::I32Load { &Operator::I32Load { memory } => wasm_encoder::Instruction::I32Load(memory.into()),
memarg: memory.into(), &Operator::I64Load { memory } => wasm_encoder::Instruction::I64Load(memory.into()),
}, &Operator::F32Load { memory } => wasm_encoder::Instruction::F32Load(memory.into()),
&Operator::I64Load { memory } => wasmparser::Operator::I64Load { &Operator::F64Load { memory } => wasm_encoder::Instruction::F64Load(memory.into()),
memarg: memory.into(), &Operator::I32Load8S { memory } => wasm_encoder::Instruction::I32Load8_S(memory.into()),
}, &Operator::I32Load8U { memory } => wasm_encoder::Instruction::I32Load8_U(memory.into()),
&Operator::F32Load { memory } => wasmparser::Operator::F32Load { &Operator::I32Load16S { memory } => {
memarg: memory.into(), wasm_encoder::Instruction::I32Load16_S(memory.into())
}, }
&Operator::F64Load { memory } => wasmparser::Operator::F64Load { &Operator::I32Load16U { memory } => {
memarg: memory.into(), wasm_encoder::Instruction::I32Load16_U(memory.into())
}, }
&Operator::I32Load8S { memory } => wasmparser::Operator::I32Load8S { &Operator::I64Load8S { memory } => wasm_encoder::Instruction::I64Load8_S(memory.into()),
memarg: memory.into(), &Operator::I64Load8U { memory } => wasm_encoder::Instruction::I64Load8_U(memory.into()),
}, &Operator::I64Load16S { memory } => {
&Operator::I32Load8U { memory } => wasmparser::Operator::I32Load8U { wasm_encoder::Instruction::I64Load16_S(memory.into())
memarg: memory.into(), }
}, &Operator::I64Load16U { memory } => {
&Operator::I32Load16S { memory } => wasmparser::Operator::I32Load16S { wasm_encoder::Instruction::I64Load16_U(memory.into())
memarg: memory.into(), }
}, &Operator::I64Load32S { memory } => {
&Operator::I32Load16U { memory } => wasmparser::Operator::I32Load16U { wasm_encoder::Instruction::I64Load32_S(memory.into())
memarg: memory.into(), }
}, &Operator::I64Load32U { memory } => {
&Operator::I64Load8S { memory } => wasmparser::Operator::I64Load8S { wasm_encoder::Instruction::I64Load32_U(memory.into())
memarg: memory.into(), }
}, &Operator::I32Store { memory } => wasm_encoder::Instruction::I32Store(memory.into()),
&Operator::I64Load8U { memory } => wasmparser::Operator::I64Load8U { &Operator::I64Store { memory } => wasm_encoder::Instruction::I64Store(memory.into()),
memarg: memory.into(), &Operator::F32Store { memory } => wasm_encoder::Instruction::F32Store(memory.into()),
}, &Operator::F64Store { memory } => wasm_encoder::Instruction::F64Store(memory.into()),
&Operator::I64Load16S { memory } => wasmparser::Operator::I64Load16S { &Operator::I32Store8 { memory } => wasm_encoder::Instruction::I32Store8(memory.into()),
memarg: memory.into(), &Operator::I32Store16 { memory } => {
}, wasm_encoder::Instruction::I32Store16(memory.into())
&Operator::I64Load16U { memory } => wasmparser::Operator::I64Load16U { }
memarg: memory.into(), &Operator::I64Store8 { memory } => wasm_encoder::Instruction::I64Store8(memory.into()),
}, &Operator::I64Store16 { memory } => {
&Operator::I64Load32S { memory } => wasmparser::Operator::I64Load32S { wasm_encoder::Instruction::I64Store16(memory.into())
memarg: memory.into(), }
}, &Operator::I64Store32 { memory } => {
&Operator::I64Load32U { memory } => wasmparser::Operator::I64Load32U { wasm_encoder::Instruction::I64Store32(memory.into())
memarg: memory.into(), }
}, &Operator::I32Const { value } => wasm_encoder::Instruction::I32Const(value),
&Operator::I32Store { memory } => wasmparser::Operator::I32Store { &Operator::I64Const { value } => wasm_encoder::Instruction::I64Const(value),
memarg: memory.into(), &Operator::F32Const { value } => {
}, wasm_encoder::Instruction::F32Const(f32::from_bits(value.bits()))
&Operator::I64Store { memory } => wasmparser::Operator::I64Store { }
memarg: memory.into(), &Operator::F64Const { value } => {
}, wasm_encoder::Instruction::F64Const(f64::from_bits(value.bits()))
&Operator::F32Store { memory } => wasmparser::Operator::F32Store { }
memarg: memory.into(), &Operator::I32Eqz => wasm_encoder::Instruction::I32Eqz,
}, &Operator::I32Eq => wasm_encoder::Instruction::I32Eq,
&Operator::F64Store { memory } => wasmparser::Operator::F64Store { &Operator::I32Ne => wasm_encoder::Instruction::I32Neq,
memarg: memory.into(), &Operator::I32LtS => wasm_encoder::Instruction::I32LtS,
}, &Operator::I32LtU => wasm_encoder::Instruction::I32LtU,
&Operator::I32Store8 { memory } => wasmparser::Operator::I32Store8 { &Operator::I32GtS => wasm_encoder::Instruction::I32GtS,
memarg: memory.into(), &Operator::I32GtU => wasm_encoder::Instruction::I32GtU,
}, &Operator::I32LeS => wasm_encoder::Instruction::I32LeS,
&Operator::I32Store16 { memory } => wasmparser::Operator::I32Store16 { &Operator::I32LeU => wasm_encoder::Instruction::I32LeU,
memarg: memory.into(), &Operator::I32GeS => wasm_encoder::Instruction::I32GeS,
}, &Operator::I32GeU => wasm_encoder::Instruction::I32GeU,
&Operator::I64Store8 { memory } => wasmparser::Operator::I64Store8 { &Operator::I64Eqz => wasm_encoder::Instruction::I64Eqz,
memarg: memory.into(), &Operator::I64Eq => wasm_encoder::Instruction::I64Eq,
}, &Operator::I64Ne => wasm_encoder::Instruction::I64Neq,
&Operator::I64Store16 { memory } => wasmparser::Operator::I64Store16 { &Operator::I64LtS => wasm_encoder::Instruction::I64LtS,
memarg: memory.into(), &Operator::I64LtU => wasm_encoder::Instruction::I64LtU,
}, &Operator::I64GtU => wasm_encoder::Instruction::I64GtU,
&Operator::I64Store32 { memory } => wasmparser::Operator::I64Store32 { &Operator::I64GtS => wasm_encoder::Instruction::I64GtS,
memarg: memory.into(), &Operator::I64LeS => wasm_encoder::Instruction::I64LeS,
}, &Operator::I64LeU => wasm_encoder::Instruction::I64LeU,
&Operator::I32Const { value } => wasmparser::Operator::I32Const { value }, &Operator::I64GeS => wasm_encoder::Instruction::I64GeS,
&Operator::I64Const { value } => wasmparser::Operator::I64Const { value }, &Operator::I64GeU => wasm_encoder::Instruction::I64GeU,
&Operator::F32Const { value } => wasmparser::Operator::F32Const { value }, &Operator::F32Eq => wasm_encoder::Instruction::F32Eq,
&Operator::F64Const { value } => wasmparser::Operator::F64Const { value }, &Operator::F32Ne => wasm_encoder::Instruction::F32Neq,
&Operator::I32Eqz => wasmparser::Operator::I32Eqz, &Operator::F32Lt => wasm_encoder::Instruction::F32Lt,
&Operator::I32Eq => wasmparser::Operator::I32Eq, &Operator::F32Gt => wasm_encoder::Instruction::F32Gt,
&Operator::I32Ne => wasmparser::Operator::I32Ne, &Operator::F32Le => wasm_encoder::Instruction::F32Le,
&Operator::I32LtS => wasmparser::Operator::I32LtS, &Operator::F32Ge => wasm_encoder::Instruction::F32Ge,
&Operator::I32LtU => wasmparser::Operator::I32LtU, &Operator::F64Eq => wasm_encoder::Instruction::F64Eq,
&Operator::I32GtS => wasmparser::Operator::I32GtS, &Operator::F64Ne => wasm_encoder::Instruction::F64Neq,
&Operator::I32GtU => wasmparser::Operator::I32GtU, &Operator::F64Lt => wasm_encoder::Instruction::F64Lt,
&Operator::I32LeS => wasmparser::Operator::I32LeS, &Operator::F64Gt => wasm_encoder::Instruction::F64Gt,
&Operator::I32LeU => wasmparser::Operator::I32LeU, &Operator::F64Le => wasm_encoder::Instruction::F64Le,
&Operator::I32GeS => wasmparser::Operator::I32GeS, &Operator::F64Ge => wasm_encoder::Instruction::F64Ge,
&Operator::I32GeU => wasmparser::Operator::I32GeU, &Operator::I32Clz => wasm_encoder::Instruction::I32Clz,
&Operator::I64Eqz => wasmparser::Operator::I64Eqz, &Operator::I32Ctz => wasm_encoder::Instruction::I32Ctz,
&Operator::I64Eq => wasmparser::Operator::I64Eq, &Operator::I32Popcnt => wasm_encoder::Instruction::I32Popcnt,
&Operator::I64Ne => wasmparser::Operator::I64Ne, &Operator::I32Add => wasm_encoder::Instruction::I32Add,
&Operator::I64LtS => wasmparser::Operator::I64LtS, &Operator::I32Sub => wasm_encoder::Instruction::I32Sub,
&Operator::I64LtU => wasmparser::Operator::I64LtU, &Operator::I32Mul => wasm_encoder::Instruction::I32Mul,
&Operator::I64GtU => wasmparser::Operator::I64GtU, &Operator::I32DivS => wasm_encoder::Instruction::I32DivS,
&Operator::I64GtS => wasmparser::Operator::I64GtS, &Operator::I32DivU => wasm_encoder::Instruction::I32DivU,
&Operator::I64LeS => wasmparser::Operator::I64LeS, &Operator::I32RemS => wasm_encoder::Instruction::I32RemS,
&Operator::I64LeU => wasmparser::Operator::I64LeU, &Operator::I32RemU => wasm_encoder::Instruction::I32RemU,
&Operator::I64GeS => wasmparser::Operator::I64GeS, &Operator::I32And => wasm_encoder::Instruction::I32And,
&Operator::I64GeU => wasmparser::Operator::I64GeU, &Operator::I32Or => wasm_encoder::Instruction::I32Or,
&Operator::F32Eq => wasmparser::Operator::F32Eq, &Operator::I32Xor => wasm_encoder::Instruction::I32Xor,
&Operator::F32Ne => wasmparser::Operator::F32Ne, &Operator::I32Shl => wasm_encoder::Instruction::I32Shl,
&Operator::F32Lt => wasmparser::Operator::F32Lt, &Operator::I32ShrS => wasm_encoder::Instruction::I32ShrS,
&Operator::F32Gt => wasmparser::Operator::F32Gt, &Operator::I32ShrU => wasm_encoder::Instruction::I32ShrU,
&Operator::F32Le => wasmparser::Operator::F32Le, &Operator::I32Rotl => wasm_encoder::Instruction::I32Rotl,
&Operator::F32Ge => wasmparser::Operator::F32Ge, &Operator::I32Rotr => wasm_encoder::Instruction::I32Rotr,
&Operator::F64Eq => wasmparser::Operator::F64Eq, &Operator::I64Clz => wasm_encoder::Instruction::I64Clz,
&Operator::F64Ne => wasmparser::Operator::F64Ne, &Operator::I64Ctz => wasm_encoder::Instruction::I64Ctz,
&Operator::F64Lt => wasmparser::Operator::F64Lt, &Operator::I64Popcnt => wasm_encoder::Instruction::I64Popcnt,
&Operator::F64Gt => wasmparser::Operator::F64Gt, &Operator::I64Add => wasm_encoder::Instruction::I64Add,
&Operator::F64Le => wasmparser::Operator::F64Le, &Operator::I64Sub => wasm_encoder::Instruction::I64Sub,
&Operator::F64Ge => wasmparser::Operator::F64Ge, &Operator::I64Mul => wasm_encoder::Instruction::I64Mul,
&Operator::I32Clz => wasmparser::Operator::I32Clz, &Operator::I64DivS => wasm_encoder::Instruction::I64DivS,
&Operator::I32Ctz => wasmparser::Operator::I32Ctz, &Operator::I64DivU => wasm_encoder::Instruction::I64DivU,
&Operator::I32Popcnt => wasmparser::Operator::I32Popcnt, &Operator::I64RemS => wasm_encoder::Instruction::I64RemS,
&Operator::I32Add => wasmparser::Operator::I32Add, &Operator::I64RemU => wasm_encoder::Instruction::I64RemU,
&Operator::I32Sub => wasmparser::Operator::I32Sub, &Operator::I64And => wasm_encoder::Instruction::I64And,
&Operator::I32Mul => wasmparser::Operator::I32Mul, &Operator::I64Or => wasm_encoder::Instruction::I64Or,
&Operator::I32DivS => wasmparser::Operator::I32DivS, &Operator::I64Xor => wasm_encoder::Instruction::I64Xor,
&Operator::I32DivU => wasmparser::Operator::I32DivU, &Operator::I64Shl => wasm_encoder::Instruction::I64Shl,
&Operator::I32RemS => wasmparser::Operator::I32RemS, &Operator::I64ShrS => wasm_encoder::Instruction::I64ShrS,
&Operator::I32RemU => wasmparser::Operator::I32RemU, &Operator::I64ShrU => wasm_encoder::Instruction::I64ShrU,
&Operator::I32And => wasmparser::Operator::I32And, &Operator::I64Rotl => wasm_encoder::Instruction::I64Rotl,
&Operator::I32Or => wasmparser::Operator::I32Or, &Operator::I64Rotr => wasm_encoder::Instruction::I64Rotr,
&Operator::I32Xor => wasmparser::Operator::I32Xor, &Operator::F32Abs => wasm_encoder::Instruction::F32Abs,
&Operator::I32Shl => wasmparser::Operator::I32Shl, &Operator::F32Neg => wasm_encoder::Instruction::F32Neg,
&Operator::I32ShrS => wasmparser::Operator::I32ShrS, &Operator::F32Ceil => wasm_encoder::Instruction::F32Ceil,
&Operator::I32ShrU => wasmparser::Operator::I32ShrU, &Operator::F32Floor => wasm_encoder::Instruction::F32Floor,
&Operator::I32Rotl => wasmparser::Operator::I32Rotl, &Operator::F32Trunc => wasm_encoder::Instruction::F32Trunc,
&Operator::I32Rotr => wasmparser::Operator::I32Rotr, &Operator::F32Nearest => wasm_encoder::Instruction::F32Nearest,
&Operator::I64Clz => wasmparser::Operator::I64Clz, &Operator::F32Sqrt => wasm_encoder::Instruction::F32Sqrt,
&Operator::I64Ctz => wasmparser::Operator::I64Ctz, &Operator::F32Add => wasm_encoder::Instruction::F32Add,
&Operator::I64Popcnt => wasmparser::Operator::I64Popcnt, &Operator::F32Sub => wasm_encoder::Instruction::F32Sub,
&Operator::I64Add => wasmparser::Operator::I64Add, &Operator::F32Mul => wasm_encoder::Instruction::F32Mul,
&Operator::I64Sub => wasmparser::Operator::I64Sub, &Operator::F32Div => wasm_encoder::Instruction::F32Div,
&Operator::I64Mul => wasmparser::Operator::I64Mul, &Operator::F32Min => wasm_encoder::Instruction::F32Min,
&Operator::I64DivS => wasmparser::Operator::I64DivS, &Operator::F32Max => wasm_encoder::Instruction::F32Max,
&Operator::I64DivU => wasmparser::Operator::I64DivU, &Operator::F32Copysign => wasm_encoder::Instruction::F32Copysign,
&Operator::I64RemS => wasmparser::Operator::I64RemS, &Operator::F64Abs => wasm_encoder::Instruction::F64Abs,
&Operator::I64RemU => wasmparser::Operator::I64RemU, &Operator::F64Neg => wasm_encoder::Instruction::F64Neg,
&Operator::I64And => wasmparser::Operator::I64And, &Operator::F64Ceil => wasm_encoder::Instruction::F64Ceil,
&Operator::I64Or => wasmparser::Operator::I64Or, &Operator::F64Floor => wasm_encoder::Instruction::F64Floor,
&Operator::I64Xor => wasmparser::Operator::I64Xor, &Operator::F64Trunc => wasm_encoder::Instruction::F64Trunc,
&Operator::I64Shl => wasmparser::Operator::I64Shl, &Operator::F64Nearest => wasm_encoder::Instruction::F64Nearest,
&Operator::I64ShrS => wasmparser::Operator::I64ShrS, &Operator::F64Sqrt => wasm_encoder::Instruction::F64Sqrt,
&Operator::I64ShrU => wasmparser::Operator::I64ShrU, &Operator::F64Add => wasm_encoder::Instruction::F64Add,
&Operator::I64Rotl => wasmparser::Operator::I64Rotl, &Operator::F64Sub => wasm_encoder::Instruction::F64Sub,
&Operator::I64Rotr => wasmparser::Operator::I64Rotr, &Operator::F64Mul => wasm_encoder::Instruction::F64Mul,
&Operator::F32Abs => wasmparser::Operator::F32Abs, &Operator::F64Div => wasm_encoder::Instruction::F64Div,
&Operator::F32Neg => wasmparser::Operator::F32Neg, &Operator::F64Min => wasm_encoder::Instruction::F64Min,
&Operator::F32Ceil => wasmparser::Operator::F32Ceil, &Operator::F64Max => wasm_encoder::Instruction::F64Max,
&Operator::F32Floor => wasmparser::Operator::F32Floor, &Operator::F64Copysign => wasm_encoder::Instruction::F64Copysign,
&Operator::F32Trunc => wasmparser::Operator::F32Trunc, &Operator::I32WrapI64 => wasm_encoder::Instruction::I32WrapI64,
&Operator::F32Nearest => wasmparser::Operator::F32Nearest, &Operator::I32TruncF32S => wasm_encoder::Instruction::I32TruncF32S,
&Operator::F32Sqrt => wasmparser::Operator::F32Sqrt, &Operator::I32TruncF32U => wasm_encoder::Instruction::I32TruncF32U,
&Operator::F32Add => wasmparser::Operator::F32Add, &Operator::I32TruncF64S => wasm_encoder::Instruction::I32TruncF64S,
&Operator::F32Sub => wasmparser::Operator::F32Sub, &Operator::I32TruncF64U => wasm_encoder::Instruction::I32TruncF64U,
&Operator::F32Mul => wasmparser::Operator::F32Mul, &Operator::I64ExtendI32S => wasm_encoder::Instruction::I64ExtendI32S,
&Operator::F32Div => wasmparser::Operator::F32Div, &Operator::I64ExtendI32U => wasm_encoder::Instruction::I64ExtendI32U,
&Operator::F32Min => wasmparser::Operator::F32Min, &Operator::I64TruncF32S => wasm_encoder::Instruction::I64TruncF32S,
&Operator::F32Max => wasmparser::Operator::F32Max, &Operator::I64TruncF32U => wasm_encoder::Instruction::I64TruncF32U,
&Operator::F32Copysign => wasmparser::Operator::F32Copysign, &Operator::I64TruncF64S => wasm_encoder::Instruction::I64TruncF64S,
&Operator::F64Abs => wasmparser::Operator::F64Abs, &Operator::I64TruncF64U => wasm_encoder::Instruction::I64TruncF64U,
&Operator::F64Neg => wasmparser::Operator::F64Neg, &Operator::F32ConvertI32S => wasm_encoder::Instruction::F32ConvertI32S,
&Operator::F64Ceil => wasmparser::Operator::F64Ceil, &Operator::F32ConvertI32U => wasm_encoder::Instruction::F32ConvertI32U,
&Operator::F64Floor => wasmparser::Operator::F64Floor, &Operator::F32ConvertI64S => wasm_encoder::Instruction::F32ConvertI64S,
&Operator::F64Trunc => wasmparser::Operator::F64Trunc, &Operator::F32ConvertI64U => wasm_encoder::Instruction::F32ConvertI64U,
&Operator::F64Nearest => wasmparser::Operator::F64Nearest, &Operator::F32DemoteF64 => wasm_encoder::Instruction::F32DemoteF64,
&Operator::F64Sqrt => wasmparser::Operator::F64Sqrt, &Operator::F64ConvertI32S => wasm_encoder::Instruction::F64ConvertI32S,
&Operator::F64Add => wasmparser::Operator::F64Add, &Operator::F64ConvertI32U => wasm_encoder::Instruction::F64ConvertI32U,
&Operator::F64Sub => wasmparser::Operator::F64Sub, &Operator::F64ConvertI64S => wasm_encoder::Instruction::F64ConvertI64S,
&Operator::F64Mul => wasmparser::Operator::F64Mul, &Operator::F64ConvertI64U => wasm_encoder::Instruction::F64ConvertI64U,
&Operator::F64Div => wasmparser::Operator::F64Div, &Operator::F64PromoteF32 => wasm_encoder::Instruction::F64PromoteF32,
&Operator::F64Min => wasmparser::Operator::F64Min, &Operator::I32Extend8S => wasm_encoder::Instruction::I32Extend8S,
&Operator::F64Max => wasmparser::Operator::F64Max, &Operator::I32Extend16S => wasm_encoder::Instruction::I32Extend16S,
&Operator::F64Copysign => wasmparser::Operator::F64Copysign, &Operator::I64Extend8S => wasm_encoder::Instruction::I64Extend8S,
&Operator::I32WrapI64 => wasmparser::Operator::I32WrapI64, &Operator::I64Extend16S => wasm_encoder::Instruction::I64Extend16S,
&Operator::I32TruncF32S => wasmparser::Operator::I32TruncF32S, &Operator::I64Extend32S => wasm_encoder::Instruction::I64Extend32S,
&Operator::I32TruncF32U => wasmparser::Operator::I32TruncF32U, &Operator::I32TruncSatF32S => wasm_encoder::Instruction::I32TruncSatF32S,
&Operator::I32TruncF64S => wasmparser::Operator::I32TruncF64S, &Operator::I32TruncSatF32U => wasm_encoder::Instruction::I32TruncSatF32U,
&Operator::I32TruncF64U => wasmparser::Operator::I32TruncF64U, &Operator::I32TruncSatF64S => wasm_encoder::Instruction::I32TruncSatF64S,
&Operator::I64ExtendI32S => wasmparser::Operator::I64ExtendI32S, &Operator::I32TruncSatF64U => wasm_encoder::Instruction::I32TruncSatF64U,
&Operator::I64ExtendI32U => wasmparser::Operator::I64ExtendI32U, &Operator::I64TruncSatF32S => wasm_encoder::Instruction::I64TruncSatF32S,
&Operator::I64TruncF32S => wasmparser::Operator::I64TruncF32S, &Operator::I64TruncSatF32U => wasm_encoder::Instruction::I64TruncSatF32U,
&Operator::I64TruncF32U => wasmparser::Operator::I64TruncF32U, &Operator::I64TruncSatF64S => wasm_encoder::Instruction::I64TruncSatF64S,
&Operator::I64TruncF64S => wasmparser::Operator::I64TruncF64S, &Operator::I64TruncSatF64U => wasm_encoder::Instruction::I64TruncSatF64U,
&Operator::I64TruncF64U => wasmparser::Operator::I64TruncF64U, &Operator::F32ReinterpretI32 => wasm_encoder::Instruction::F32ReinterpretI32,
&Operator::F32ConvertI32S => wasmparser::Operator::F32ConvertI32S, &Operator::F64ReinterpretI64 => wasm_encoder::Instruction::F64ReinterpretI64,
&Operator::F32ConvertI32U => wasmparser::Operator::F32ConvertI32U, &Operator::I32ReinterpretF32 => wasm_encoder::Instruction::I32ReinterpretF32,
&Operator::F32ConvertI64S => wasmparser::Operator::F32ConvertI64S, &Operator::I64ReinterpretF64 => wasm_encoder::Instruction::I64ReinterpretF64,
&Operator::F32ConvertI64U => wasmparser::Operator::F32ConvertI64U, &Operator::TableGet { table } => wasm_encoder::Instruction::TableGet { table },
&Operator::F32DemoteF64 => wasmparser::Operator::F32DemoteF64, &Operator::TableSet { table } => wasm_encoder::Instruction::TableSet { table },
&Operator::F64ConvertI32S => wasmparser::Operator::F64ConvertI32S, &Operator::TableGrow { table } => wasm_encoder::Instruction::TableGrow { table },
&Operator::F64ConvertI32U => wasmparser::Operator::F64ConvertI32U, &Operator::TableSize { table } => wasm_encoder::Instruction::TableSize { table },
&Operator::F64ConvertI64S => wasmparser::Operator::F64ConvertI64S, &Operator::MemorySize { mem } => wasm_encoder::Instruction::MemorySize(mem),
&Operator::F64ConvertI64U => wasmparser::Operator::F64ConvertI64U, &Operator::MemoryGrow { mem } => wasm_encoder::Instruction::MemoryGrow(mem),
&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,
},
} }
} }
} }
@ -727,12 +701,22 @@ impl std::convert::From<MemoryImmediate> for Memory {
} }
} }
impl std::convert::Into<MemoryImmediate> for Memory { impl std::convert::Into<wasm_encoder::MemArg> for Memory {
fn into(self) -> MemoryImmediate { fn into(self) -> wasm_encoder::MemArg {
MemoryImmediate { wasm_encoder::MemArg {
align: self.align, align: self.align as u32,
offset: self.offset, offset: self.offset as u64,
memory: self.memory as u32, 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),
}
}