From 2214c1701bf94ae2bcfd7d1a06d64bcbf3e23e07 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Wed, 26 Oct 2022 08:15:18 -0700 Subject: [PATCH] Remove wasm_encoder backend, and bring in binaryen bindings --- Cargo.toml | 3 +- src/backend/binaryen.rs | 776 ++++++++++++++++++++++++++++++++++++++++ src/backend/mod.rs | 11 +- src/ir.rs | 142 +------- src/lib.rs | 4 +- src/ops.rs | 243 ------------- 6 files changed, 784 insertions(+), 395 deletions(-) create mode 100644 src/backend/binaryen.rs diff --git a/Cargo.toml b/Cargo.toml index 670e929..ad65155 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ edition = "2018" [dependencies] wasmparser = { git = 'https://github.com/cfallin/wasm-tools', rev = '03a81b6a6ed4d5d9730fa71bf65636a3b1538ce7' } -wasm-encoder = "0.8" anyhow = "1.0" structopt = "0.3" log = "0.4" @@ -16,3 +15,5 @@ env_logger = "0.9" fxhash = "0.2" smallvec = "1.7" rayon = "1.5" +lazy_static = "1.4" +libc = "0.2" diff --git a/src/backend/binaryen.rs b/src/backend/binaryen.rs new file mode 100644 index 0000000..6cb1a33 --- /dev/null +++ b/src/backend/binaryen.rs @@ -0,0 +1,776 @@ +//! Binaryen bindings. + +use anyhow::{bail, Result}; +use lazy_static::lazy_static; +use libc::{c_char, c_void}; +use std::ffi::{CStr, CString}; + +#[derive(Debug)] +pub struct Module(BinaryenModule); +#[derive(Clone, Copy, Debug)] +pub struct Function(BinaryenModule, BinaryenFunction); +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Expression(BinaryenModule, BinaryenExpression); +#[derive(Clone, Copy, Debug)] +pub struct Export(BinaryenModule, BinaryenExport); + +impl Module { + pub fn read(data: &[u8]) -> Result { + let ptr = unsafe { BinaryenModuleRead(data.as_ptr(), data.len()) }; + if ptr.is_null() { + bail!("Failed to parse module"); + } + Ok(Module(ptr)) + } + + pub fn num_funcs(&self) -> usize { + unsafe { BinaryenGetNumFunctions(self.0) as usize } + } + + pub fn func(&self, index: usize) -> Function { + assert!(index < self.num_funcs()); + let ptr = unsafe { BinaryenGetFunctionByIndex(self.0, index as u32) }; + assert!(!ptr.is_null()); + Function(self.0, ptr) + } + + pub fn func_by_name(&self, name: &str) -> Option { + let c_str = CString::new(name).unwrap(); + let ptr = unsafe { BinaryenGetFunction(self.0, c_str.as_ptr()) }; + if !ptr.is_null() { + Some(Function(self.0, ptr)) + } else { + None + } + } + + pub fn num_exports(&self) -> usize { + unsafe { BinaryenGetNumExports(self.0) as usize } + } + + pub fn export_by_name(&self, name: &str) -> Option { + let c_str = CString::new(name).unwrap(); + let ptr = unsafe { BinaryenGetExport(self.0, c_str.as_ptr()) }; + if !ptr.is_null() { + Some(Export(self.0, ptr)) + } else { + None + } + } + + pub fn export(&self, index: usize) -> Export { + assert!(index < self.num_exports()); + let ptr = unsafe { BinaryenGetExportByIndex(self.0, index as u32) }; + assert!(!ptr.is_null()); + Export(self.0, ptr) + } + + pub fn module(&self) -> BinaryenModule { + self.0 + } +} + +impl Drop for Module { + fn drop(&mut self) { + unsafe { + BinaryenModuleDispose(self.0); + } + } +} + +impl Function { + pub fn body(&self) -> Option { + let body = unsafe { BinaryenFunctionGetBody(self.1) }; + if body.is_null() { + None + } else { + Some(Expression(self.0, body)) + } + } + + pub fn name(&self) -> &str { + let s = unsafe { CStr::from_ptr(BinaryenFunctionGetName(self.1)) }; + s.to_str().unwrap() + } +} + +impl Export { + pub fn name(&self) -> &str { + let s = unsafe { CStr::from_ptr(BinaryenExportGetName(self.1)) }; + s.to_str().unwrap() + } + + pub fn value(&self) -> &str { + let s = unsafe { CStr::from_ptr(BinaryenExportGetValue(self.1)) }; + s.to_str().unwrap() + } + + pub fn into_function(&self, module: &Module) -> Option { + let kind = unsafe { BinaryenExportGetKind(self.1) }; + if kind == unsafe { BinaryenExternalFunction() } { + let name = self.value(); + module.func_by_name(name) + } else { + None + } + } +} + +struct ExprIds { + nop: u32, + block: u32, + if_: u32, + loop_: u32, + break_: u32, + switch: u32, + call: u32, + call_indirect: u32, + local_get: u32, + local_set: u32, + global_get: u32, + global_set: u32, + table_get: u32, + table_set: u32, + load: u32, + store: u32, + const_: u32, + unary: u32, + binary: u32, + select: u32, + drop_: u32, + return_: u32, + unreachable: u32, +} + +impl ExprIds { + fn get() -> Self { + Self { + nop: unsafe { BinaryenNopId() }, + block: unsafe { BinaryenBlockId() }, + if_: unsafe { BinaryenIfId() }, + loop_: unsafe { BinaryenLoopId() }, + break_: unsafe { BinaryenBreakId() }, + switch: unsafe { BinaryenSwitchId() }, + call: unsafe { BinaryenCallId() }, + call_indirect: unsafe { BinaryenCallIndirectId() }, + local_get: unsafe { BinaryenLocalGetId() }, + local_set: unsafe { BinaryenLocalSetId() }, + global_get: unsafe { BinaryenGlobalGetId() }, + global_set: unsafe { BinaryenGlobalSetId() }, + table_get: unsafe { BinaryenTableGetId() }, + table_set: unsafe { BinaryenTableSetId() }, + load: unsafe { BinaryenLoadId() }, + store: unsafe { BinaryenStoreId() }, + const_: unsafe { BinaryenConstId() }, + unary: unsafe { BinaryenUnaryId() }, + binary: unsafe { BinaryenBinaryId() }, + select: unsafe { BinaryenSelectId() }, + drop_: unsafe { BinaryenDropId() }, + return_: unsafe { BinaryenReturnId() }, + unreachable: unsafe { BinaryenUnreachableId() }, + } + } +} + +lazy_static! { + static ref EXPR_IDS: ExprIds = ExprIds::get(); +} + +struct TypeIds { + none_t: u32, + i32_t: u32, + i64_t: u32, + f32_t: u32, + f64_t: u32, +} + +impl TypeIds { + fn get() -> Self { + TypeIds { + none_t: unsafe { BinaryenTypeNone() }, + i32_t: unsafe { BinaryenTypeInt32() }, + i64_t: unsafe { BinaryenTypeInt64() }, + f32_t: unsafe { BinaryenTypeFloat32() }, + f64_t: unsafe { BinaryenTypeFloat64() }, + } + } +} + +lazy_static! { + static ref TYPE_IDS: TypeIds = TypeIds::get(); +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Type { + None, + I32, + I64, + F32, + F64, +} + +impl Type { + fn from_kind(kind: u32) -> Option { + let tys = &*TYPE_IDS; + if kind == tys.none_t { + Some(Type::None) + } else if kind == tys.i32_t { + Some(Type::I32) + } else if kind == tys.i64_t { + Some(Type::I64) + } else if kind == tys.f32_t { + Some(Type::F32) + } else if kind == tys.f64_t { + Some(Type::F64) + } else { + None + } + } + + fn to_kind(&self) -> u32 { + let tys = &*TYPE_IDS; + match self { + &Type::None => tys.none_t, + &Type::I32 => tys.i32_t, + &Type::I64 => tys.i64_t, + &Type::F32 => tys.f32_t, + &Type::F64 => tys.f64_t, + } + } +} + +fn name_to_string(name: *const c_char) -> Option { + if name.is_null() { + None + } else { + Some(unsafe { CStr::from_ptr(name).to_str().unwrap().to_string() }) + } +} + +impl Expression { + pub fn unpack(&self) -> Expr { + if self.1.is_null() { + return Expr::None; + } + + let kind = unsafe { BinaryenExpressionGetId(self.1) }; + let kinds = &*EXPR_IDS; + + if kind == kinds.nop { + Expr::Nop + } else if kind == kinds.block { + let name = name_to_string(unsafe { BinaryenBlockGetName(self.1) }); + let children = unsafe { + (0..BinaryenBlockGetNumChildren(self.1)) + .map(|i| Expression(self.0, BinaryenBlockGetChildAt(self.1, i))) + .collect::>() + }; + Expr::Block(name, children) + } else if kind == kinds.if_ { + let cond = unsafe { Expression(self.0, BinaryenIfGetCondition(self.1)) }; + let if_true = unsafe { Expression(self.0, BinaryenIfGetIfTrue(self.1)) }; + let if_false = unsafe { Expression(self.0, BinaryenIfGetIfFalse(self.1)) }; + Expr::If(cond, if_true, if_false) + } else if kind == kinds.loop_ { + let name = name_to_string(unsafe { BinaryenLoopGetName(self.1) }); + let value = unsafe { Expression(self.0, BinaryenLoopGetBody(self.1)) }; + Expr::Loop(name, value) + } else if kind == kinds.break_ { + let name = name_to_string(unsafe { BinaryenBreakGetName(self.1) }).unwrap(); + let value = unsafe { Expression(self.0, BinaryenBreakGetValue(self.1)) }; + Expr::Break(name, value) + } else if kind == kinds.switch { + let n = unsafe { BinaryenSwitchGetNumNames(self.1) }; + let default_name = name_to_string(unsafe { BinaryenSwitchGetDefaultName(self.1) }); + let names = (0..n) + .map(|i| name_to_string(unsafe { BinaryenSwitchGetNameAt(self.1, i) })) + .collect::>(); + let value = unsafe { Expression(self.0, BinaryenSwitchGetValue(self.1)) }; + let cond = Expression(self.0, unsafe { BinaryenSwitchGetCondition(self.1) }); + Expr::Switch(cond, value, default_name, names) + } else if kind == kinds.call { + let target = name_to_string(unsafe { BinaryenCallGetTarget(self.1) }).unwrap(); + let n = unsafe { BinaryenCallGetNumOperands(self.1) }; + let args = (0..n) + .map(|i| unsafe { Expression(self.0, BinaryenCallGetOperandAt(self.1, i)) }) + .collect::>(); + Expr::Call(target, args) + } else if kind == kinds.call_indirect { + let target = unsafe { Expression(self.0, BinaryenCallIndirectGetTarget(self.1)) }; + let n = unsafe { BinaryenCallIndirectGetNumOperands(self.1) }; + let args = (0..n) + .map(|i| unsafe { Expression(self.0, BinaryenCallIndirectGetOperandAt(self.1, i)) }) + .collect::>(); + Expr::CallIndirect(target, args) + } else if kind == kinds.local_get { + let index = unsafe { BinaryenLocalGetGetIndex(self.1) }; + Expr::LocalGet(index) + } else if kind == kinds.local_set { + let index = unsafe { BinaryenLocalSetGetIndex(self.1) }; + let value = unsafe { Expression(self.0, BinaryenLocalSetGetValue(self.1)) }; + Expr::LocalSet(index, value) + } else if kind == kinds.global_get { + let name = name_to_string(unsafe { BinaryenGlobalGetGetName(self.1) }).unwrap(); + Expr::GlobalGet(name) + } else if kind == kinds.global_set { + let name = name_to_string(unsafe { BinaryenGlobalSetGetName(self.1) }).unwrap(); + let value = unsafe { Expression(self.0, BinaryenGlobalSetGetValue(self.1)) }; + Expr::GlobalSet(name, value) + } else if kind == kinds.table_get { + let name = name_to_string(unsafe { BinaryenTableGetGetTable(self.1) }).unwrap(); + let index = unsafe { Expression(self.0, BinaryenTableGetGetIndex(self.1)) }; + Expr::TableGet(name, index) + } else if kind == kinds.table_set { + let name = name_to_string(unsafe { BinaryenTableSetGetTable(self.1) }).unwrap(); + let index = unsafe { Expression(self.0, BinaryenTableSetGetIndex(self.1)) }; + let value = unsafe { Expression(self.0, BinaryenTableSetGetIndex(self.1)) }; + Expr::TableSet(name, index, value) + } else if kind == kinds.load { + let ptr = unsafe { Expression(self.0, BinaryenLoadGetPtr(self.1)) }; + let offset = unsafe { BinaryenLoadGetOffset(self.1) }; + Expr::Load(ptr, offset) + } else if kind == kinds.store { + let ptr = unsafe { Expression(self.0, BinaryenStoreGetPtr(self.1)) }; + let offset = unsafe { BinaryenStoreGetOffset(self.1) }; + let value = unsafe { Expression(self.0, BinaryenStoreGetValue(self.1)) }; + Expr::Store(ptr, offset, value) + } else if kind == kinds.const_ { + let value = match self.ty() { + Type::None => unreachable!(), + Type::I32 => Value::I32(unsafe { BinaryenConstGetValueI32(self.1) }), + Type::I64 => Value::I64(unsafe { BinaryenConstGetValueI64(self.1) }), + Type::F32 => Value::F32(unsafe { BinaryenConstGetValueF32(self.1).to_bits() }), + Type::F64 => Value::F64(unsafe { BinaryenConstGetValueF64(self.1).to_bits() }), + }; + Expr::Const(value) + } else if kind == kinds.unary { + let op = unsafe { BinaryenUnaryGetOp(self.1) }; + let value = unsafe { Expression(self.0, BinaryenUnaryGetValue(self.1)) }; + Expr::Unary(UnaryOp::from_kind(op), value) + } else if kind == kinds.binary { + let op = unsafe { BinaryenBinaryGetOp(self.1) }; + let left = unsafe { Expression(self.0, BinaryenBinaryGetLeft(self.1)) }; + let right = unsafe { Expression(self.0, BinaryenBinaryGetRight(self.1)) }; + Expr::Binary(BinaryOp::from_kind(op), left, right) + } else if kind == kinds.select { + let cond = unsafe { Expression(self.0, BinaryenSelectGetCondition(self.1)) }; + let if_true = unsafe { Expression(self.0, BinaryenSelectGetIfTrue(self.1)) }; + let if_false = unsafe { Expression(self.0, BinaryenSelectGetIfFalse(self.1)) }; + Expr::Select(cond, if_true, if_false) + } else if kind == kinds.drop_ { + let value = unsafe { Expression(self.0, BinaryenDropGetValue(self.1)) }; + Expr::Drop(value) + } else if kind == kinds.return_ { + let value = unsafe { Expression(self.0, BinaryenReturnGetValue(self.1)) }; + Expr::Return(value) + } else if kind == kinds.unreachable { + Expr::Unreachable + } else { + panic!("Unknown kind: {}", kind); + } + } + + pub fn ty(&self) -> Type { + Type::from_kind(unsafe { BinaryenExpressionGetType(self.1) }).unwrap() + } + + pub fn deep_clone(&self) -> Self { + Expression(self.0, unsafe { BinaryenExpressionCopy(self.0, self.1) }) + } + + pub fn module(&self) -> BinaryenModule { + self.0 + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum UnaryOp { + Other(u32), +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BinaryOp { + I32Add, + I32Sub, + I32Shl, + I32ShrU, + I32ShrS, + Other(u32), +} + +struct OpIds { + i32_add: u32, + i32_sub: u32, + i32_shl: u32, + i32_shr_u: u32, + i32_shr_s: u32, +} + +impl OpIds { + fn get() -> Self { + OpIds { + i32_add: unsafe { BinaryenAddInt32() }, + i32_sub: unsafe { BinaryenSubInt32() }, + i32_shl: unsafe { BinaryenShlInt32() }, + i32_shr_u: unsafe { BinaryenShrUInt32() }, + i32_shr_s: unsafe { BinaryenShrSInt32() }, + } + } +} + +lazy_static! { + static ref OP_IDS: OpIds = OpIds::get(); +} + +impl UnaryOp { + fn from_kind(kind: u32) -> UnaryOp { + UnaryOp::Other(kind) + } +} + +impl BinaryOp { + fn from_kind(kind: u32) -> BinaryOp { + let ids = &*OP_IDS; + if kind == ids.i32_add { + BinaryOp::I32Add + } else if kind == ids.i32_sub { + BinaryOp::I32Sub + } else if kind == ids.i32_shl { + BinaryOp::I32Shl + } else if kind == ids.i32_shr_s { + BinaryOp::I32ShrS + } else if kind == ids.i32_shr_u { + BinaryOp::I32ShrU + } else { + BinaryOp::Other(kind) + } + } +} + +#[derive(Clone, Debug)] +pub enum Expr { + None, + Nop, + Block(Option, Vec), + If(Expression, Expression, Expression), + Loop(Option, Expression), + Break(String, Expression), + Switch(Expression, Expression, Option, Vec>), + Call(String, Vec), + CallIndirect(Expression, Vec), + LocalGet(u32), + LocalSet(u32, Expression), + GlobalGet(String), + GlobalSet(String, Expression), + TableGet(String, Expression), + TableSet(String, Expression, Expression), + Load(Expression, u32), + Store(Expression, u32, Expression), + Const(Value), + Unary(UnaryOp, Expression), + Binary(BinaryOp, Expression, Expression), + Select(Expression, Expression, Expression), + Drop(Expression), + Return(Expression), + Unreachable, +} + +impl Expr { + pub fn visit_children(&self, mut f: F) { + self.visit_children_and_ret(|e| { + f(e); + let ret: Option<()> = None; + ret + }); + } + + pub fn visit_children_and_ret Option>( + &self, + mut f: F, + ) -> Option { + match self { + &Expr::None => None, + &Expr::Block(_, ref subexprs) => { + for e in subexprs { + if let Some(ret) = f(*e) { + return Some(ret); + } + } + None + } + &Expr::If(cond, if_true, if_false) => { + if let Some(ret) = f(cond) { + return Some(ret); + } + if let Some(ret) = f(if_true) { + return Some(ret); + } + if let Some(ret) = f(if_false) { + return Some(ret); + } + None + } + &Expr::Loop(_, body) => f(body), + &Expr::Drop(expr) => f(expr), + + &Expr::Break(_, value) => f(value), + &Expr::Switch(index, value, ..) => { + if let Some(ret) = f(index) { + return Some(ret); + } + if let Some(ret) = f(value) { + return Some(ret); + } + None + } + &Expr::Call(_, ref ops) => { + for op in ops { + if let Some(ret) = f(*op) { + return Some(ret); + } + } + None + } + &Expr::CallIndirect(target, ref ops) => { + if let Some(ret) = f(target) { + return Some(ret); + } + for op in ops { + if let Some(ret) = f(*op) { + return Some(ret); + } + } + None + } + &Expr::LocalGet(_) => None, + &Expr::LocalSet(_, expr) => f(expr), + &Expr::GlobalGet(_) => None, + &Expr::GlobalSet(_, expr) => f(expr), + &Expr::TableGet(_, index) => f(index), + &Expr::TableSet(_, index, value) => { + if let Some(val) = f(index) { + return Some(val); + } + if let Some(val) = f(value) { + return Some(val); + } + None + } + &Expr::Load(ptr, _) => f(ptr), + &Expr::Store(ptr, _, value) => { + if let Some(ret) = f(ptr) { + return Some(ret); + } + if let Some(ret) = f(value) { + return Some(ret); + } + None + } + &Expr::Const(_) => None, + &Expr::Unary(_, value) => f(value), + &Expr::Binary(_, left, right) => { + if let Some(ret) = f(left) { + return Some(ret); + } + if let Some(ret) = f(right) { + return Some(ret); + } + None + } + &Expr::Select(cond, if_true, if_false) => { + if let Some(ret) = f(cond) { + return Some(ret); + } + if let Some(ret) = f(if_true) { + return Some(ret); + } + if let Some(ret) = f(if_false) { + return Some(ret); + } + None + } + &Expr::Return(expr) => f(expr), + &Expr::Unreachable => None, + &Expr::Nop => None, + } + } + + pub fn to_expression(&self, module: BinaryenModule) -> Expression { + match self { + &Expr::Const(Value::I32(value)) => unsafe { + let literal = BinaryenLiteralInt32(value); + Expression(module, BinaryenConst(module, literal)) + }, + &Expr::LocalSet(idx, value) => unsafe { + Expression(module, BinaryenLocalSet(module, idx, value.1)) + }, + _ => unimplemented!(), + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Value { + I32(i32), + I64(i64), + F32(u32), + F64(u64), +} + +pub type BinaryenModule = *const c_void; +type BinaryenFunction = *const c_void; +type BinaryenExpression = *const c_void; +type BinaryenExport = *const c_void; + +#[link(name = "binaryen")] +extern "C" { + fn BinaryenModuleRead(data: *const u8, len: usize) -> BinaryenModule; + fn BinaryenModuleDispose(ptr: BinaryenModule); + fn BinaryenGetNumFunctions(ptr: BinaryenModule) -> u32; + fn BinaryenGetFunctionByIndex(ptr: BinaryenModule, index: u32) -> BinaryenFunction; + fn BinaryenGetFunction(ptr: BinaryenModule, name: *const c_char) -> BinaryenFunction; + fn BinaryenFunctionGetBody(ptr: BinaryenFunction) -> BinaryenExpression; + fn BinaryenFunctionGetName(ptr: BinaryenFunction) -> *const c_char; + fn BinaryenGetExport(ptr: BinaryenModule, name: *const c_char) -> BinaryenExport; + fn BinaryenGetNumExports(ptr: BinaryenModule) -> u32; + fn BinaryenGetExportByIndex(ptr: BinaryenModule, index: u32) -> BinaryenExport; + fn BinaryenExportGetName(ptr: BinaryenFunction) -> *const c_char; + fn BinaryenExportGetValue(ptr: BinaryenFunction) -> *const c_char; + fn BinaryenExportGetKind(ptr: BinaryenFunction) -> u32; + fn BinaryenExternalFunction() -> u32; + + fn BinaryenExpressionGetId(ptr: BinaryenExpression) -> u32; + fn BinaryenExpressionGetType(ptr: BinaryenExpression) -> u32; + fn BinaryenExpressionCopy( + ptr: BinaryenExpression, + module: BinaryenModule, + ) -> BinaryenExpression; + + fn BinaryenConstGetValueI32(ptr: BinaryenExpression) -> i32; + fn BinaryenConstGetValueI64(ptr: BinaryenExpression) -> i64; + fn BinaryenConstGetValueF32(ptr: BinaryenExpression) -> f32; + fn BinaryenConstGetValueF64(ptr: BinaryenExpression) -> f64; + + fn BinaryenBlockGetNumChildren(ptr: BinaryenExpression) -> u32; + fn BinaryenBlockGetChildAt(ptr: BinaryenExpression, index: u32) -> BinaryenExpression; + fn BinaryenBlockGetName(ptr: BinaryenExpression) -> *const c_char; + + fn BinaryenLoopGetBody(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenLoopGetName(ptr: BinaryenExpression) -> *const c_char; + + fn BinaryenIfGetCondition(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenIfGetIfTrue(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenIfGetIfFalse(ptr: BinaryenExpression) -> BinaryenExpression; + + fn BinaryenBreakGetName(ptr: BinaryenExpression) -> *const c_char; + fn BinaryenBreakGetValue(ptr: BinaryenExpression) -> BinaryenExpression; + + fn BinaryenDropGetValue(ptr: BinaryenExpression) -> BinaryenExpression; + + fn BinaryenSwitchGetNumNames(ptr: BinaryenExpression) -> u32; + fn BinaryenSwitchGetNameAt(ptr: BinaryenExpression, index: u32) -> *const c_char; + fn BinaryenSwitchGetDefaultName(ptr: BinaryenExpression) -> *const c_char; + fn BinaryenSwitchGetCondition(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenSwitchGetValue(ptr: BinaryenExpression) -> BinaryenExpression; + + fn BinaryenCallGetTarget(ptr: BinaryenExpression) -> *const c_char; + fn BinaryenCallGetNumOperands(ptr: BinaryenExpression) -> u32; + fn BinaryenCallGetOperandAt(ptr: BinaryenExpression, index: u32) -> BinaryenExpression; + + fn BinaryenCallIndirectGetTarget(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenCallIndirectGetNumOperands(ptr: BinaryenExpression) -> u32; + fn BinaryenCallIndirectGetOperandAt(ptr: BinaryenExpression, index: u32) -> BinaryenExpression; + + fn BinaryenLocalGetGetIndex(ptr: BinaryenExpression) -> u32; + fn BinaryenLocalSetGetIndex(ptr: BinaryenExpression) -> u32; + fn BinaryenLocalSetGetValue(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenGlobalGetGetName(ptr: BinaryenExpression) -> *const c_char; + fn BinaryenGlobalSetGetName(ptr: BinaryenExpression) -> *const c_char; + fn BinaryenGlobalSetGetValue(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenTableGetGetTable(ptr: BinaryenExpression) -> *const c_char; + fn BinaryenTableGetGetIndex(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenTableSetGetTable(ptr: BinaryenExpression) -> *const c_char; + fn BinaryenTableSetGetIndex(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenTableSetGetValue(ptr: BinaryenExpression) -> BinaryenExpression; + + fn BinaryenLoadGetPtr(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenLoadGetOffset(ptr: BinaryenExpression) -> u32; + fn BinaryenStoreGetPtr(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenStoreGetValue(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenStoreGetOffset(ptr: BinaryenExpression) -> u32; + + fn BinaryenUnaryGetOp(ptr: BinaryenExpression) -> u32; + fn BinaryenUnaryGetValue(ptr: BinaryenExpression) -> BinaryenExpression; + + fn BinaryenBinaryGetOp(ptr: BinaryenExpression) -> u32; + fn BinaryenBinaryGetLeft(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenBinaryGetRight(ptr: BinaryenExpression) -> BinaryenExpression; + + fn BinaryenSelectGetIfTrue(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenSelectGetIfFalse(ptr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenSelectGetCondition(ptr: BinaryenExpression) -> BinaryenExpression; + + fn BinaryenReturnGetValue(ptr: BinaryenExpression) -> BinaryenExpression; + + fn BinaryenGetNumMemorySegments(module: BinaryenModule) -> u32; + fn BinaryenGetMemorySegmentByteOffset(module: BinaryenModule, index: u32) -> u32; + fn BinaryenGetMemorySegmentByteLength(module: BinaryenModule, index: u32) -> usize; + fn BinaryenCopyMemorySegmentData(module: BinaryenModule, index: u32, buffer: *mut u8); + + fn BinaryenNopId() -> u32; + fn BinaryenBlockId() -> u32; + fn BinaryenIfId() -> u32; + fn BinaryenLoopId() -> u32; + fn BinaryenBreakId() -> u32; + fn BinaryenSwitchId() -> u32; + fn BinaryenCallId() -> u32; + fn BinaryenCallIndirectId() -> u32; + fn BinaryenLocalGetId() -> u32; + fn BinaryenLocalSetId() -> u32; + fn BinaryenGlobalGetId() -> u32; + fn BinaryenGlobalSetId() -> u32; + fn BinaryenTableGetId() -> u32; + fn BinaryenTableSetId() -> u32; + fn BinaryenLoadId() -> u32; + fn BinaryenStoreId() -> u32; + fn BinaryenConstId() -> u32; + fn BinaryenUnaryId() -> u32; + fn BinaryenBinaryId() -> u32; + fn BinaryenSelectId() -> u32; + fn BinaryenDropId() -> u32; + fn BinaryenReturnId() -> u32; + fn BinaryenMemorySizeId() -> u32; + fn BinaryenMemoryGrowId() -> u32; + fn BinaryenUnreachableId() -> u32; + fn BinaryenPopId() -> u32; + + fn BinaryenTypeNone() -> u32; + fn BinaryenTypeInt32() -> u32; + fn BinaryenTypeInt64() -> u32; + fn BinaryenTypeFloat32() -> u32; + fn BinaryenTypeFloat64() -> u32; + + fn BinaryenAddInt32() -> u32; + fn BinaryenSubInt32() -> u32; + fn BinaryenShlInt32() -> u32; + fn BinaryenShrUInt32() -> u32; + fn BinaryenShrSInt32() -> u32; + + fn BinaryenConst(module: BinaryenModule, lit: BinaryenLiteral) -> BinaryenExpression; + fn BinaryenLocalSet( + module: BinaryenModule, + index: u32, + value: BinaryenExpression, + ) -> BinaryenExpression; + + fn BinaryenLiteralInt32(x: i32) -> BinaryenLiteral; + fn BinaryenLiteralInt64(x: i64) -> BinaryenLiteral; + fn BinaryenLiteralFloat32Bits(x: i32) -> BinaryenLiteral; + fn BinaryenLiteralFloat64Bits(x: i64) -> BinaryenLiteral; +} + +#[repr(C)] +struct BinaryenLiteral { + _pad0: usize, + _pad1: [u8; 16], +} diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 85c66ad..86b4492 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,11 +1,4 @@ //! Backend: IR to Wasm. -mod structured; -pub use structured::*; -mod serialize; -pub use serialize::*; -mod locations; -pub use locations::*; -mod r#final; -pub use r#final::*; - +mod binaryen; +pub use binaryen::*; diff --git a/src/ir.rs b/src/ir.rs index 2fabbe7..594d437 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -1,15 +1,8 @@ //! Intermediate representation for Wasm. -use crate::{ - backend::{produce_func_wasm, BlockOrder, Locations, LoopNest, SerializedBody, WasmRegion}, - cfg::CFGInfo, - frontend, - ops::ty_to_valty, - Operator, -}; +use crate::{frontend, Operator}; use anyhow::Result; -use rayon::prelude::*; -use wasmparser::{FuncType, SectionReader, Type}; +use wasmparser::{FuncType, Type}; pub type SignatureId = usize; pub type FuncId = usize; @@ -465,135 +458,6 @@ impl<'a> Module<'a> { } pub fn to_wasm_bytes(&self) -> Vec { - // Do most of the compilation in parallel: up to the - // generation of the function that we emit into the final code - // seciton in order. Only the "final parts assembly" needs to - // be serialized. - let compiled: Vec<(u32, wasm_encoder::Function)> = self - .funcs - .par_iter() - .filter_map(|func| match func { - &FuncDecl::Body(sig, ref body) => { - let cfg = CFGInfo::new(body); - let loopnest = LoopNest::compute(&cfg); - let regions = WasmRegion::compute(&cfg, &loopnest); - let blockorder = BlockOrder::compute(body, &cfg, ®ions); - let serialized = SerializedBody::compute(body, &cfg, &blockorder); - log::trace!("serialized: {:?}", serialized); - let locations = Locations::compute(body, &serialized); - log::trace!("locations: {:?}", locations); - let func_body = produce_func_wasm(body, &serialized, &locations); - log::trace!("body: {:?}", func_body); - - let mut locals: Vec<(u32, wasm_encoder::ValType)> = vec![]; - for local_ty in func_body.locals { - if locals.len() > 0 && locals.last().unwrap().1 == local_ty { - locals.last_mut().unwrap().0 += 1; - } else { - locals.push((1, local_ty)); - } - } - let mut func = wasm_encoder::Function::new(locals); - - for inst in func_body.operators { - func.instruction(&inst); - } - - Some((sig as u32, func)) - } - _ => None, - }) - .collect(); - - // Build the final code section and function-type section. - let mut code_section = wasm_encoder::CodeSection::new(); - let mut func_section = wasm_encoder::FunctionSection::new(); - for (sig, func) in compiled { - func_section.function(sig as u32); - code_section.function(&func); - } - - // Build the final function-signature (type) section. - let mut type_section = wasm_encoder::TypeSection::new(); - for sig in &self.signatures { - let params: Vec = - sig.params.iter().map(|&ty| ty_to_valty(ty)).collect(); - let returns: Vec = - sig.returns.iter().map(|&ty| ty_to_valty(ty)).collect(); - type_section.function(params, returns); - } - - // Now do a final pass over the original bytes with - // wasmparser, replacing the type section, function section, - // and code section. (TODO: allow new imports to be added - // too?) - let parser = wasmparser::Parser::new(0); - let mut module = wasm_encoder::Module::new(); - for payload in parser.parse_all(self.orig_bytes) { - match payload.unwrap() { - wasmparser::Payload::TypeSection(..) => { - module.section(&type_section); - } - wasmparser::Payload::FunctionSection(..) => { - module.section(&func_section); - } - wasmparser::Payload::CodeSectionStart { .. } => { - module.section(&code_section); - } - wasmparser::Payload::CodeSectionEntry(..) => {} - wasmparser::Payload::ImportSection(reader) => { - let range = reader.range(); - let bytes = &self.orig_bytes[range.start..range.end]; - module.section(&wasm_encoder::RawSection { id: 2, data: bytes }); - } - wasmparser::Payload::TableSection(reader) => { - let range = reader.range(); - let bytes = &self.orig_bytes[range.start..range.end]; - module.section(&wasm_encoder::RawSection { id: 4, data: bytes }); - } - wasmparser::Payload::MemorySection(reader) => { - let range = reader.range(); - let bytes = &self.orig_bytes[range.start..range.end]; - module.section(&wasm_encoder::RawSection { id: 5, data: bytes }); - } - wasmparser::Payload::GlobalSection(reader) => { - let range = reader.range(); - let bytes = &self.orig_bytes[range.start..range.end]; - module.section(&wasm_encoder::RawSection { id: 6, data: bytes }); - } - wasmparser::Payload::ExportSection(reader) => { - let range = reader.range(); - let bytes = &self.orig_bytes[range.start..range.end]; - module.section(&wasm_encoder::RawSection { id: 7, data: bytes }); - } - wasmparser::Payload::StartSection { range, .. } => { - let bytes = &self.orig_bytes[range.start..range.end]; - module.section(&wasm_encoder::RawSection { id: 8, data: bytes }); - } - wasmparser::Payload::ElementSection(reader) => { - let range = reader.range(); - let bytes = &self.orig_bytes[range.start..range.end]; - module.section(&wasm_encoder::RawSection { id: 9, data: bytes }); - } - wasmparser::Payload::DataSection(reader) => { - let range = reader.range(); - let bytes = &self.orig_bytes[range.start..range.end]; - module.section(&wasm_encoder::RawSection { - id: 11, - data: bytes, - }); - } - wasmparser::Payload::DataCountSection { range, .. } => { - let bytes = &self.orig_bytes[range.start..range.end]; - module.section(&wasm_encoder::RawSection { - id: 12, - data: bytes, - }); - } - _ => {} - } - } - - module.finish() + todo!("use Binaryen") } } diff --git a/src/lib.rs b/src/lib.rs index 0791c12..16be75e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,7 @@ #![allow(dead_code)] -// Re-export wasmparser and wasmencoder for easier use of the right -// version by our embedders. -pub use wasm_encoder; +// Re-export wasmparser for easier use of the right version by our embedders. pub use wasmparser; mod backend; diff --git a/src/ops.rs b/src/ops.rs index 624479d..a2bb73c 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -468,229 +468,6 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator { } } -impl<'a> std::convert::Into> for Operator { - fn into(self) -> wasm_encoder::Instruction<'static> { - match &self { - &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 } => { - wasm_encoder::Instruction::GlobalGet(global_index) - } - &Operator::GlobalSet { global_index } => { - wasm_encoder::Instruction::GlobalSet(global_index) - } - &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), - } - } -} - impl std::convert::From for Memory { fn from(value: MemoryImmediate) -> Memory { Memory { @@ -700,23 +477,3 @@ impl std::convert::From for Memory { } } } - -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), - } -}