Remove wasm_encoder backend, and bring in binaryen bindings

This commit is contained in:
Chris Fallin 2022-10-26 08:15:18 -07:00
parent e2be302e47
commit 2214c1701b
6 changed files with 784 additions and 395 deletions

View file

@ -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"

776
src/backend/binaryen.rs Normal file
View file

@ -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<Module> {
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<Function> {
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<Export> {
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<Expression> {
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<Function> {
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<Type> {
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<String> {
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::<Vec<_>>()
};
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::<Vec<_>>();
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::<Vec<_>>();
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::<Vec<_>>();
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<String>, Vec<Expression>),
If(Expression, Expression, Expression),
Loop(Option<String>, Expression),
Break(String, Expression),
Switch(Expression, Expression, Option<String>, Vec<Option<String>>),
Call(String, Vec<Expression>),
CallIndirect(Expression, Vec<Expression>),
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<F: FnMut(Expression)>(&self, mut f: F) {
self.visit_children_and_ret(|e| {
f(e);
let ret: Option<()> = None;
ret
});
}
pub fn visit_children_and_ret<R, F: FnMut(Expression) -> Option<R>>(
&self,
mut f: F,
) -> Option<R> {
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],
}

View file

@ -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::*;

142
src/ir.rs
View file

@ -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<u8> {
// 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, &regions);
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<wasm_encoder::ValType> =
sig.params.iter().map(|&ty| ty_to_valty(ty)).collect();
let returns: Vec<wasm_encoder::ValType> =
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")
}
}

View file

@ -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;

View file

@ -468,229 +468,6 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator {
}
}
impl<'a> std::convert::Into<wasm_encoder::Instruction<'static>> 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<MemoryImmediate> for Memory {
fn from(value: MemoryImmediate) -> Memory {
Memory {
@ -700,23 +477,3 @@ impl std::convert::From<MemoryImmediate> for Memory {
}
}
}
impl std::convert::Into<wasm_encoder::MemArg> 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),
}
}