WIP.
This commit is contained in:
parent
d72ef25052
commit
71a8d489ce
|
@ -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)?;
|
||||
|
|
|
@ -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<Module<'_>> {
|
||||
|
@ -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<Type>, Vec<Type>) {
|
||||
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));
|
||||
(
|
||||
|
|
36
src/ir.rs
36
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<wasmparser::Type> 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::*;
|
||||
|
|
100
src/ir/display.rs
Normal file
100
src/ir/display.rs
Normal file
|
@ -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::<Vec<_>>();
|
||||
let ret_tys = self
|
||||
.0
|
||||
.rets
|
||||
.iter()
|
||||
.map(|&ty| format!("{}", ty))
|
||||
.collect::<Vec<_>>();
|
||||
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::<Vec<_>>();
|
||||
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::<Vec<_>>();
|
||||
let tys = tys.iter().map(|&ty| format!("{}", ty)).collect::<Vec<_>>();
|
||||
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(())
|
||||
}
|
||||
}
|
|
@ -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)]
|
||||
|
|
|
@ -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<Func, FuncDecl>,
|
||||
signatures: EntityVec<Signature, FuncType>,
|
||||
signatures: EntityVec<Signature, SignatureData>,
|
||||
globals: EntityVec<Global, Type>,
|
||||
tables: EntityVec<Table, Type>,
|
||||
|
||||
dirty_funcs: FxHashSet<Func>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct SignatureData {
|
||||
pub params: Vec<Type>,
|
||||
pub returns: Vec<Type>,
|
||||
}
|
||||
|
||||
impl From<&wasmparser::FuncType> for SignatureData {
|
||||
fn from(fty: &wasmparser::FuncType) -> Self {
|
||||
Self {
|
||||
params: fty
|
||||
.params
|
||||
.iter()
|
||||
.map(|&ty| ty.into())
|
||||
.collect::<Vec<Type>>(),
|
||||
returns: fty
|
||||
.returns
|
||||
.iter()
|
||||
.map(|&ty| ty.into())
|
||||
.collect::<Vec<Type>>(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<wasmparser::FuncType> 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<Item = (Func, &'b FuncDecl)> {
|
||||
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<Vec<u8>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn display<'b>(&'b self) -> ModuleDisplay<'b>
|
||||
where
|
||||
'b: 'a,
|
||||
{
|
||||
ModuleDisplay(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Value>, Vec<Type>),
|
||||
PickOutput(Value, usize, Type),
|
||||
|
@ -15,7 +13,6 @@ pub enum ValueDef {
|
|||
impl ValueDef {
|
||||
pub fn visit_uses<F: FnMut(Value)>(&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<F: FnMut(&mut Value)>(&mut self, mut f: F) {
|
||||
match self {
|
||||
&mut ValueDef::Arg { .. } => {}
|
||||
&mut ValueDef::BlockParam { .. } => {}
|
||||
&mut ValueDef::Operator(_, ref mut args, _) => {
|
||||
for arg in args {
|
||||
|
|
209
src/op_traits.rs
209
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<Vec<SideEffect>> {
|
|||
}
|
||||
}
|
||||
|
||||
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 { .. }
|
||||
|
|
16
src/ops.rs
16
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),
|
||||
}),
|
||||
|
|
Loading…
Reference in a new issue