waffle/src/backend/binaryen.rs
Chris Fallin 7b804b02d7
WIP.
2022-11-21 22:33:19 -08:00

1633 lines
59 KiB
Rust

//! Binaryen bindings.
use crate::entity::EntityRef;
use crate::ir;
use crate::{Ieee32, Ieee64};
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);
pub type BinaryenIndex = u32;
pub type BinaryenType = usize;
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 write(&self) -> Result<Vec<u8>> {
let result = unsafe { BinaryenModuleAllocateAndWrite(self.0, std::ptr::null()) };
if result.binary.is_null() {
bail!("Failed to serialize module");
}
let slice = unsafe {
std::slice::from_raw_parts(
result.binary as *const c_void as *const u8,
result.binary_bytes as usize,
)
};
Ok(slice.to_vec())
}
pub fn new() -> Result<Module> {
let ptr = unsafe { BinaryenModuleCreate() };
if ptr.is_null() {
bail!("Failed to allocate module");
}
Ok(Module(ptr))
}
pub fn add_global(&self, ty: ir::Type, mutable: bool, value: Option<u64>) -> ir::Global {
let b_ty = Type::from(ty).to_binaryen();
let value = value.unwrap_or(0);
let init = match ty {
ir::Type::I32 => Expression::const_i32(self, value as i32),
ir::Type::I64 => Expression::const_i64(self, value as i64),
ir::Type::F32 => Expression::const_f32(self, Ieee32::from_bits(value as u32)),
ir::Type::F64 => Expression::const_f64(self, Ieee64::from_bits(value)),
_ => panic!("Unsupported type"),
};
let num = unsafe { BinaryenGetNumGlobals(self.0) };
let name = CString::new(format!("global{}", num)).unwrap();
let global = unsafe { BinaryenAddGlobal(self.0, name.as_ptr(), b_ty, mutable, init.1) };
assert!(!global.is_null());
ir::Global::from(num)
}
pub fn add_table(&self, ty: ir::Type, init: usize, max: Option<u32>) -> ir::Table {
let ty = Type::from(ty).to_binaryen();
let num = unsafe { BinaryenGetNumTables(self.0) };
let max = max.unwrap_or(0);
let name = CString::new(format!("table{}", num)).unwrap();
let table = unsafe {
BinaryenAddTable(
self.0,
name.as_ptr(),
init as BinaryenIndex,
max as BinaryenIndex,
ty,
)
};
assert!(!table.is_null());
ir::Table::from(num)
}
pub fn add_table_elem(&self, table: ir::Table, index: usize, elt: ir::Func) {
log::trace!("add_table_elem: func {}", elt);
let table_name = unsafe {
BinaryenTableGetName(BinaryenGetTableByIndex(
self.0,
table.index() as BinaryenIndex,
))
};
let func_name = compute_func_name(elt);
let func_name_ptr = func_name.as_ptr();
let offset = Expression::const_i32(self, index as i32);
let name = CString::new(format!("seg_{}_{}", table.index(), index)).unwrap();
let seg = unsafe {
BinaryenAddActiveElementSegment(
self.0,
table_name,
name.as_ptr(),
&func_name_ptr as *const *const c_char,
1,
offset.1,
)
};
assert!(!seg.is_null());
}
pub fn add_mem(
&self,
init_pages: usize,
max_pages: Option<usize>,
segments: &[ir::MemorySegment],
) -> ir::Memory {
let seg_passive = vec![false; segments.len()];
let seg_offset = segments
.iter()
.map(|seg| Expression::const_i32(self, seg.offset as i32).1)
.collect::<Vec<_>>();
let seg_data = segments
.iter()
.map(|seg| seg.data.as_ptr() as *const c_char)
.collect::<Vec<_>>();
let seg_size = segments
.iter()
.map(|seg| seg.data.len() as BinaryenIndex)
.collect::<Vec<_>>();
// Binaryen does not support multi-memory.
unsafe {
BinaryenSetMemory(
self.0,
init_pages as BinaryenIndex,
max_pages.unwrap_or(0) as BinaryenIndex,
std::ptr::null(),
seg_data.as_ptr(),
seg_passive.as_ptr(),
seg_offset.as_ptr(),
seg_size.as_ptr(),
segments.len() as BinaryenIndex,
false,
);
}
ir::Memory::from(0)
}
pub fn add_table_import(&self, table: ir::Table, module: &str, name: &str) {
let table_name = unsafe {
BinaryenTableGetName(BinaryenGetTableByIndex(
self.0,
table.index() as BinaryenIndex,
))
};
let c_module = std::ffi::CString::new(module).unwrap();
let c_name = std::ffi::CString::new(name).unwrap();
unsafe {
BinaryenAddTableImport(self.0, table_name, c_module.as_ptr(), c_name.as_ptr());
}
}
pub fn add_func_import(
&self,
func: ir::Func,
module: &str,
name: &str,
params: &[ir::Type],
results: &[ir::Type],
) {
let num = unsafe { BinaryenGetNumFunctions(self.0) } as usize;
assert_eq!(num, func.index());
let c_module = std::ffi::CString::new(module).unwrap();
let c_name = std::ffi::CString::new(name).unwrap();
let params = tys_to_binaryen(params.iter().copied());
let results = tys_to_binaryen(results.iter().copied());
let internal_name = compute_func_name(func);
unsafe {
BinaryenAddFunctionImport(
self.0,
internal_name.as_ptr(),
c_module.as_ptr(),
c_name.as_ptr(),
params,
results,
);
}
}
pub fn add_global_import(
&self,
global: ir::Global,
module: &str,
name: &str,
ty: ir::Type,
mutable: bool,
) {
let global_name = unsafe {
BinaryenGlobalGetName(BinaryenGetGlobalByIndex(
self.0,
global.index() as BinaryenIndex,
))
};
let c_module = std::ffi::CString::new(module).unwrap();
let c_name = std::ffi::CString::new(name).unwrap();
let ty = Type::from(ty).to_binaryen();
unsafe {
BinaryenAddGlobalImport(
self.0,
global_name,
c_module.as_ptr(),
c_name.as_ptr(),
ty,
mutable,
);
}
}
pub fn add_table_export(&self, table: ir::Table, name: &str) {
let c_name = CString::new(name).unwrap();
let name = unsafe {
BinaryenTableGetName(BinaryenGetTableByIndex(
self.0,
table.index() as BinaryenIndex,
))
};
unsafe {
BinaryenAddTableExport(self.0, name, c_name.as_ptr());
}
}
pub fn add_func_export(&self, func: ir::Func, name: &str) {
log::trace!("add_func_export: func {}", func);
let c_name = CString::new(name).unwrap();
let name = compute_func_name(func);
unsafe {
BinaryenAddFunctionExport(self.0, name.as_ptr(), c_name.as_ptr());
}
}
pub fn add_global_export(&self, global: ir::Global, name: &str) {
let c_name = CString::new(name).unwrap();
let name = unsafe {
BinaryenGlobalGetName(BinaryenGetGlobalByIndex(
self.0,
global.index() as BinaryenIndex,
))
};
unsafe {
BinaryenAddGlobalExport(self.0, name, c_name.as_ptr());
}
}
pub fn add_memory_export(&self, mem: ir::Memory, name: &str) {
assert_eq!(mem.index(), 0);
let c_name = CString::new(name).unwrap();
unsafe {
BinaryenAddMemoryExport(self.0, std::ptr::null(), c_name.as_ptr());
}
}
}
impl Drop for Module {
fn drop(&mut self) {
unsafe {
BinaryenModuleDispose(self.0);
}
}
}
fn compute_func_name(func: ir::Func) -> CString {
CString::new(format!("func{}", func.index())).unwrap()
}
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 set_body(&mut self, body: Expression) {
unsafe {
BinaryenFunctionSetBody(self.0, body.1);
}
}
pub fn name(&self) -> &str {
let s = unsafe { CStr::from_ptr(BinaryenFunctionGetName(self.1)) };
s.to_str().unwrap()
}
pub fn create(
module: &mut Module,
params: impl Iterator<Item = ir::Type>,
results: impl Iterator<Item = ir::Type>,
locals: impl Iterator<Item = ir::Type>,
body: Expression,
) -> Function {
let params = tys_to_binaryen(params);
let results = tys_to_binaryen(results);
let locals: Vec<BinaryenType> = locals.map(|ty| Type::from(ty).to_binaryen()).collect();
let num = unsafe { BinaryenGetNumFunctions(module.0) };
let name = compute_func_name(ir::Func::new(num as usize));
log::debug!("creating func {:?}", name);
let ptr = unsafe {
BinaryenAddFunction(
module.0,
name.as_ptr(),
params,
results,
locals.as_ptr(),
locals.len() as BinaryenIndex,
body.1,
)
};
Function(module.0, ptr)
}
pub fn add_local(&mut self, ty: ir::Type) -> usize {
(unsafe { BinaryenFunctionAddVar(self.1, Type::from(ty).to_binaryen()) }) as usize
}
}
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()
}
}
struct TypeIds {
none_t: BinaryenType,
i32_t: BinaryenType,
i64_t: BinaryenType,
f32_t: BinaryenType,
f64_t: BinaryenType,
v128_t: BinaryenType,
funcref_t: BinaryenType,
}
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() },
v128_t: unsafe { BinaryenTypeVec128() },
funcref_t: unsafe { BinaryenTypeFuncref() },
}
}
}
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,
V128,
FuncRef,
}
impl Type {
pub(crate) fn to_binaryen(&self) -> BinaryenType {
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,
&Type::V128 => tys.v128_t,
&Type::FuncRef => tys.funcref_t,
}
}
}
impl From<ir::Type> for Type {
fn from(ty: ir::Type) -> Self {
match ty {
ir::Type::I32 => Type::I32,
ir::Type::I64 => Type::I64,
ir::Type::F32 => Type::F32,
ir::Type::F64 => Type::F64,
ir::Type::V128 => Type::V128,
ir::Type::FuncRef => Type::FuncRef,
}
}
}
pub fn tys_to_binaryen(tys: impl Iterator<Item = ir::Type>) -> BinaryenType {
let tys: Vec<BinaryenType> = tys.map(|ty| Type::from(ty).to_binaryen()).collect();
unsafe { BinaryenTypeCreate(tys.as_ptr(), tys.len() as BinaryenIndex) }
}
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 module(&self) -> BinaryenModule {
self.0
}
pub fn block(module: &Module, exprs: &[Expression]) -> Expression {
let children = exprs.iter().map(|expr| expr.1).collect::<Vec<_>>();
Expression(module.0, unsafe {
BinaryenBlock(
module.0,
/* name = */ std::ptr::null(),
children.as_ptr(),
children.len() as BinaryenIndex,
BinaryenUndefined(),
)
})
}
pub fn block_append_child(&mut self, child: Expression) {
unsafe {
BinaryenBlockAppendChild(self.1, child.1);
}
}
pub fn nop(module: &Module) -> Expression {
Expression(module.0, unsafe { BinaryenNop(module.0) })
}
pub fn unreachable(module: &Module) -> Expression {
Expression(module.0, unsafe { BinaryenUnreachable(module.0) })
}
pub fn call(
module: &Module,
func: ir::Func,
args: &[Expression],
tys: &[ir::Type],
) -> Expression {
// Look up the function's name.
let func_name = compute_func_name(func);
// Create the appropriate type for return.
let ret_tuple_ty = tys_to_binaryen(tys.iter().copied());
let args = args.iter().map(|expr| expr.1).collect::<Vec<_>>();
let expr = unsafe {
BinaryenCall(
module.0,
func_name.as_ptr(),
args.as_ptr(),
args.len() as BinaryenIndex,
ret_tuple_ty,
)
};
Expression(module.0, expr)
}
pub fn call_indirect(
module: &Module,
table: ir::Table,
sig: &ir::SignatureData,
target: Expression,
args: &[Expression],
) -> Expression {
let param_tuple_ty = tys_to_binaryen(sig.params.iter().copied());
let ret_tuple_ty = tys_to_binaryen(sig.returns.iter().copied());
let args = args.iter().map(|expr| expr.1).collect::<Vec<_>>();
let table_name = unsafe {
BinaryenTableGetName(BinaryenGetTableByIndex(
module.0,
table.index() as BinaryenIndex,
))
};
let expr = unsafe {
BinaryenCallIndirect(
module.0,
table_name,
target.1,
args.as_ptr(),
args.len() as BinaryenIndex,
param_tuple_ty,
ret_tuple_ty,
)
};
Expression(module.0, expr)
}
pub fn local_get(module: &Module, local: ir::Local, ty: ir::Type) -> Expression {
let local = local.index() as BinaryenIndex;
let ty = Type::from(ty).to_binaryen();
let expr = unsafe { BinaryenLocalGet(module.0, local, ty) };
Expression(module.0, expr)
}
pub fn local_set(module: &Module, local: ir::Local, value: Expression) -> Expression {
let local = local.index() as BinaryenIndex;
let expr = unsafe { BinaryenLocalSet(module.0, local, value.1) };
Expression(module.0, expr)
}
pub fn local_tee(
module: &Module,
local: ir::Local,
value: Expression,
ty: ir::Type,
) -> Expression {
let local = local.index() as BinaryenIndex;
let ty = Type::from(ty).to_binaryen();
let expr = unsafe { BinaryenLocalTee(module.0, local, value.1, ty) };
Expression(module.0, expr)
}
pub fn global_get(module: &Module, global: ir::Global, ty: ir::Type) -> Expression {
let global = global.index() as BinaryenIndex;
let ty = Type::from(ty).to_binaryen();
let expr = unsafe { BinaryenGlobalGet(module.0, global, ty) };
Expression(module.0, expr)
}
pub fn global_set(module: &Module, global: ir::Global, value: Expression) -> Expression {
let global = global.index() as BinaryenIndex;
let expr = unsafe { BinaryenGlobalSet(module.0, global, value.1) };
Expression(module.0, expr)
}
pub fn select(
module: &Module,
cond: Expression,
if_true: Expression,
if_false: Expression,
ty: ir::Type,
) -> Expression {
let ty = Type::from(ty).to_binaryen();
let expr = unsafe { BinaryenSelect(module.0, cond.1, if_true.1, if_false.1, ty) };
Expression(module.0, expr)
}
pub fn expr_drop(module: &Module, value: Expression) -> Expression {
Expression(module.0, unsafe { BinaryenDrop(module.0, value.1) })
}
pub fn ret(module: &Module, values: &[Expression]) -> Expression {
let expr = if values.len() == 0 {
unsafe { BinaryenReturn(module.0, std::ptr::null()) }
} else if values.len() == 1 {
unsafe { BinaryenReturn(module.0, values[0].1) }
} else {
let exprs = values.iter().map(|e| e.1).collect::<Vec<_>>();
let tuple = unsafe {
BinaryenTupleMake(module.0, exprs.as_ptr(), exprs.len() as BinaryenIndex)
};
unsafe { BinaryenReturn(module.0, tuple) }
};
Expression(module.0, expr)
}
pub fn load(
module: &Module,
bytes: u8,
signed: bool,
offset: u32,
align: u32,
ty: ir::Type,
ptr: Expression,
mem: ir::Memory,
) -> Expression {
assert_eq!(mem.index(), 0);
let ty = Type::from(ty).to_binaryen();
let expr =
unsafe { BinaryenLoad(module.0, bytes as u32, signed, offset, align, ty, ptr.1) };
Expression(module.0, expr)
}
pub fn store(
module: &Module,
bytes: u8,
offset: u32,
align: u32,
ty: ir::Type,
ptr: Expression,
value: Expression,
mem: ir::Memory,
) -> Expression {
assert_eq!(mem.index(), 0);
let ty = Type::from(ty).to_binaryen();
let expr =
unsafe { BinaryenStore(module.0, bytes as u32, offset, align, ptr.1, value.1, ty) };
Expression(module.0, expr)
}
pub fn const_i32(module: &Module, value: i32) -> Expression {
let expr = unsafe { BinaryenConst(module.0, BinaryenLiteralInt32(value)) };
Expression(module.0, expr)
}
pub fn const_i64(module: &Module, value: i64) -> Expression {
let expr = unsafe { BinaryenConst(module.0, BinaryenLiteralInt64(value)) };
Expression(module.0, expr)
}
pub fn const_f32(module: &Module, value: Ieee32) -> Expression {
let expr =
unsafe { BinaryenConst(module.0, BinaryenLiteralFloat32Bits(value.bits() as i32)) };
Expression(module.0, expr)
}
pub fn const_f64(module: &Module, value: Ieee64) -> Expression {
let expr =
unsafe { BinaryenConst(module.0, BinaryenLiteralFloat64Bits(value.bits() as i64)) };
Expression(module.0, expr)
}
pub fn table_get(
module: &Module,
table: ir::Table,
index: Expression,
ty: ir::Type,
) -> Expression {
let table_name = unsafe {
BinaryenTableGetName(BinaryenGetTableByIndex(module.0, table.index() as u32))
};
let ty = Type::from(ty).to_binaryen();
let expr = unsafe { BinaryenTableGet(module.0, table_name, index.1, ty) };
Expression(module.0, expr)
}
pub fn table_set(
module: &Module,
table: ir::Table,
index: Expression,
value: Expression,
) -> Expression {
let table_name = unsafe {
BinaryenTableGetName(BinaryenGetTableByIndex(module.0, table.index() as u32))
};
let expr = unsafe { BinaryenTableSet(module.0, table_name, index.1, value.1) };
Expression(module.0, expr)
}
pub fn table_grow(
module: &Module,
table: ir::Table,
delta: Expression,
value: Expression,
) -> Expression {
let table_name = unsafe {
BinaryenTableGetName(BinaryenGetTableByIndex(module.0, table.index() as u32))
};
let expr = unsafe { BinaryenTableGrow(module.0, table_name, value.1, delta.1) };
Expression(module.0, expr)
}
pub fn table_size(module: &Module, table: ir::Table) -> Expression {
let table_name = unsafe {
BinaryenTableGetName(BinaryenGetTableByIndex(module.0, table.index() as u32))
};
let expr = unsafe { BinaryenTableSize(module.0, table_name) };
Expression(module.0, expr)
}
pub fn memory_size(module: &Module, mem: ir::Memory) -> Expression {
assert_eq!(mem.index(), 0);
Expression(module.0, unsafe { BinaryenMemorySize(module.0) })
}
pub fn memory_grow(module: &Module, mem: ir::Memory, delta: Expression) -> Expression {
assert_eq!(mem.index(), 0);
Expression(module.0, unsafe { BinaryenMemoryGrow(module.0, delta.1) })
}
}
macro_rules! operator {
(unary $name:tt, $bin_name:tt) => {
impl Expression {
pub fn $name(module: &Module, arg: Expression) -> Expression {
Expression(module.0, unsafe {
BinaryenUnary(module.0, $bin_name(), arg.1)
})
}
}
};
(binary $name:tt, $bin_name:tt) => {
impl Expression {
pub fn $name(module: &Module, arg0: Expression, arg1: Expression) -> Expression {
Expression(module.0, unsafe {
BinaryenBinary(module.0, $bin_name(), arg0.1, arg1.1)
})
}
}
};
}
operator!(unary i32_eqz, BinaryenEqZInt32);
operator!(binary i32_eq, BinaryenEqInt32);
operator!(binary i32_ne, BinaryenNeInt32);
operator!(binary i32_lt_s, BinaryenLtSInt32);
operator!(binary i32_lt_u, BinaryenLtUInt32);
operator!(binary i32_gt_s, BinaryenGtSInt32);
operator!(binary i32_gt_u, BinaryenGtUInt32);
operator!(binary i32_le_s, BinaryenLeSInt32);
operator!(binary i32_le_u, BinaryenLeUInt32);
operator!(binary i32_ge_s, BinaryenGeSInt32);
operator!(binary i32_ge_u, BinaryenGeUInt32);
operator!(unary i64_eqz, BinaryenEqZInt64);
operator!(binary i64_eq, BinaryenEqInt64);
operator!(binary i64_ne, BinaryenNeInt64);
operator!(binary i64_lt_s, BinaryenLtSInt64);
operator!(binary i64_lt_u, BinaryenLtUInt64);
operator!(binary i64_gt_s, BinaryenGtSInt64);
operator!(binary i64_gt_u, BinaryenGtUInt64);
operator!(binary i64_le_s, BinaryenLeSInt64);
operator!(binary i64_le_u, BinaryenLeUInt64);
operator!(binary i64_ge_s, BinaryenGeSInt64);
operator!(binary i64_ge_u, BinaryenGeUInt64);
operator!(binary f32_eq, BinaryenEqFloat32);
operator!(binary f32_ne, BinaryenNeFloat32);
operator!(binary f32_lt, BinaryenLtFloat32);
operator!(binary f32_gt, BinaryenGtFloat32);
operator!(binary f32_le, BinaryenLeFloat32);
operator!(binary f32_ge, BinaryenGeFloat32);
operator!(binary f64_eq, BinaryenEqFloat64);
operator!(binary f64_ne, BinaryenNeFloat64);
operator!(binary f64_lt, BinaryenLtFloat64);
operator!(binary f64_gt, BinaryenGtFloat64);
operator!(binary f64_le, BinaryenLeFloat64);
operator!(binary f64_ge, BinaryenGeFloat64);
operator!(unary i32_clz, BinaryenClzInt32);
operator!(unary i32_ctz, BinaryenCtzInt32);
operator!(unary i32_popcnt, BinaryenPopcntInt32);
operator!(binary i32_add, BinaryenAddInt32);
operator!(binary i32_sub, BinaryenSubInt32);
operator!(binary i32_mul, BinaryenMulInt32);
operator!(binary i32_div_s, BinaryenDivSInt32);
operator!(binary i32_div_u, BinaryenDivUInt32);
operator!(binary i32_rem_s, BinaryenRemSInt32);
operator!(binary i32_rem_u, BinaryenRemUInt32);
operator!(binary i32_and, BinaryenAndInt32);
operator!(binary i32_or, BinaryenOrInt32);
operator!(binary i32_xor, BinaryenXorInt32);
operator!(binary i32_shl, BinaryenShlInt32);
operator!(binary i32_shr_s, BinaryenShrSInt32);
operator!(binary i32_shr_u, BinaryenShrUInt32);
operator!(binary i32_rotl, BinaryenRotLInt32);
operator!(binary i32_rotr, BinaryenRotRInt32);
operator!(unary i64_clz, BinaryenClzInt64);
operator!(unary i64_ctz, BinaryenCtzInt64);
operator!(unary i64_popcnt, BinaryenPopcntInt64);
operator!(binary i64_add, BinaryenAddInt64);
operator!(binary i64_sub, BinaryenSubInt64);
operator!(binary i64_mul, BinaryenMulInt64);
operator!(binary i64_div_s, BinaryenDivSInt64);
operator!(binary i64_div_u, BinaryenDivUInt64);
operator!(binary i64_rem_s, BinaryenRemSInt64);
operator!(binary i64_rem_u, BinaryenRemUInt64);
operator!(binary i64_and, BinaryenAndInt64);
operator!(binary i64_or, BinaryenOrInt64);
operator!(binary i64_xor, BinaryenXorInt64);
operator!(binary i64_shl, BinaryenShlInt64);
operator!(binary i64_shr_s, BinaryenShrSInt64);
operator!(binary i64_shr_u, BinaryenShrUInt64);
operator!(binary i64_rotl, BinaryenRotLInt64);
operator!(binary i64_rotr, BinaryenRotRInt64);
operator!(unary f32_abs, BinaryenAbsFloat32);
operator!(unary f32_neg, BinaryenNegFloat32);
operator!(unary f32_ceil, BinaryenCeilFloat32);
operator!(unary f32_floor, BinaryenFloorFloat32);
operator!(unary f32_trunc, BinaryenTruncFloat32);
operator!(unary f32_nearest, BinaryenNearestFloat32);
operator!(unary f32_sqrt, BinaryenSqrtFloat32);
operator!(binary f32_add, BinaryenAddFloat32);
operator!(binary f32_sub, BinaryenSubFloat32);
operator!(binary f32_mul, BinaryenMulFloat32);
operator!(binary f32_div, BinaryenDivFloat32);
operator!(binary f32_min, BinaryenMinFloat32);
operator!(binary f32_max, BinaryenMaxFloat32);
operator!(binary f32_copysign, BinaryenCopySignFloat32);
operator!(unary f64_abs, BinaryenAbsFloat64);
operator!(unary f64_neg, BinaryenNegFloat64);
operator!(unary f64_ceil, BinaryenCeilFloat64);
operator!(unary f64_floor, BinaryenFloorFloat64);
operator!(unary f64_trunc, BinaryenTruncFloat64);
operator!(unary f64_nearest, BinaryenNearestFloat64);
operator!(unary f64_sqrt, BinaryenSqrtFloat64);
operator!(binary f64_add, BinaryenAddFloat64);
operator!(binary f64_sub, BinaryenSubFloat64);
operator!(binary f64_mul, BinaryenMulFloat64);
operator!(binary f64_div, BinaryenDivFloat64);
operator!(binary f64_min, BinaryenMinFloat64);
operator!(binary f64_max, BinaryenMaxFloat64);
operator!(binary f64_copysign, BinaryenCopySignFloat64);
operator!(unary i32_wrap_i64, BinaryenWrapInt64);
operator!(unary i32_trunc_f32_s, BinaryenTruncSFloat32ToInt32);
operator!(unary i32_trunc_f32_u, BinaryenTruncUFloat32ToInt32);
operator!(unary i32_trunc_f64_s, BinaryenTruncSFloat64ToInt32);
operator!(unary i32_trunc_f64_u, BinaryenTruncUFloat64ToInt32);
operator!(unary i64_extend_i32_s, BinaryenExtendSInt32);
operator!(unary i64_extend_i32_u, BinaryenExtendUInt32);
operator!(unary i64_trunc_f32_s, BinaryenTruncSFloat32ToInt64);
operator!(unary i64_trunc_f32_u, BinaryenTruncUFloat32ToInt64);
operator!(unary i64_trunc_f64_s, BinaryenTruncSFloat64ToInt64);
operator!(unary i64_trunc_f64_u, BinaryenTruncUFloat64ToInt64);
operator!(unary f32_convert_i32_s, BinaryenConvertSInt32ToFloat32);
operator!(unary f32_convert_i32_u, BinaryenConvertUInt32ToFloat32);
operator!(unary f32_convert_i64_s, BinaryenConvertSInt64ToFloat32);
operator!(unary f32_convert_i64_u, BinaryenConvertUInt64ToFloat32);
operator!(unary f32_demote_f64, BinaryenDemoteFloat64);
operator!(unary f64_convert_i32_s, BinaryenConvertSInt32ToFloat64);
operator!(unary f64_convert_i32_u, BinaryenConvertUInt32ToFloat64);
operator!(unary f64_convert_i64_s, BinaryenConvertSInt64ToFloat64);
operator!(unary f64_convert_i64_u, BinaryenConvertUInt64ToFloat64);
operator!(unary f64_promote_f32, BinaryenPromoteFloat32);
operator!(unary i32_extend_8_s, BinaryenExtendS8Int32);
operator!(unary i32_extend_16_s, BinaryenExtendS16Int32);
operator!(unary i64_extend_8_s, BinaryenExtendS8Int64);
operator!(unary i64_extend_16_s, BinaryenExtendS16Int64);
operator!(unary i64_extend_32_s, BinaryenExtendS32Int64);
operator!(unary i32_trunc_sat_f32_s, BinaryenTruncSatSFloat32ToInt32);
operator!(unary i32_trunc_sat_f32_u, BinaryenTruncSatUFloat32ToInt32);
operator!(unary i32_trunc_sat_f64_s, BinaryenTruncSatSFloat64ToInt32);
operator!(unary i32_trunc_sat_f64_u, BinaryenTruncSatUFloat64ToInt32);
operator!(unary i64_trunc_sat_f32_s, BinaryenTruncSatSFloat32ToInt64);
operator!(unary i64_trunc_sat_f32_u, BinaryenTruncSatUFloat32ToInt64);
operator!(unary i64_trunc_sat_f64_s, BinaryenTruncSatSFloat64ToInt64);
operator!(unary i64_trunc_sat_f64_u, BinaryenTruncSatUFloat64ToInt64);
operator!(unary f32_reinterpret_i32, BinaryenReinterpretInt32);
operator!(unary f64_reinterpret_i64, BinaryenReinterpretInt64);
operator!(unary i32_reinterpret_f32, BinaryenReinterpretFloat32);
operator!(unary i64_reinterpret_f64, BinaryenReinterpretFloat64);
pub type BinaryenModule = *const c_void;
type BinaryenFunction = *const c_void;
type BinaryenExpression = *const c_void;
type BinaryenExport = *const c_void;
type BinaryenRelooper = *const c_void;
type BinaryenRelooperBlock = *const c_void;
type BinaryenTable = *const c_void;
type BinaryenGlobal = *const c_void;
type BinaryenElementSegment = *const c_void;
#[repr(C)]
struct BinaryenModuleAllocateAndWriteResult {
binary: *mut c_void,
binary_bytes: libc::size_t,
source_map: *mut c_char,
}
impl Drop for BinaryenModuleAllocateAndWriteResult {
fn drop(&mut self) {
unsafe {
libc::free(self.binary);
libc::free(self.source_map as *mut c_void);
}
}
}
pub struct Relooper(BinaryenModule, BinaryenRelooper);
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct RelooperBlock(BinaryenRelooperBlock);
impl Relooper {
pub fn new(module: &Module) -> Relooper {
let ptr = unsafe { RelooperCreate(module.0) };
Relooper(module.0, ptr)
}
pub fn construct(self, entry: RelooperBlock, index_var: usize) -> Expression {
let module = self.0;
let expr = unsafe { RelooperRenderAndDispose(self.1, entry.0, index_var as BinaryenIndex) };
std::mem::forget(self);
Expression(module, expr)
}
pub fn add_block(&mut self, expr: Expression) -> RelooperBlock {
RelooperBlock(unsafe { RelooperAddBlock(self.1, expr.1) })
}
pub fn add_block_with_switch(&mut self, expr: Expression, sel: Expression) -> RelooperBlock {
RelooperBlock(unsafe { RelooperAddBlockWithSwitch(self.1, expr.1, sel.1) })
}
}
impl RelooperBlock {
pub fn cond_branch(&self, to: RelooperBlock, cond: Expression, edge: Expression) {
unsafe {
RelooperAddBranch(self.0, to.0, cond.1, edge.1);
}
}
pub fn branch(&self, to: RelooperBlock, edge: Expression) {
unsafe {
RelooperAddBranch(self.0, to.0, std::ptr::null(), edge.1);
}
}
pub fn switch(&self, to: RelooperBlock, edge: Expression, indices: &[BinaryenIndex]) {
unsafe {
RelooperAddBranchForSwitch(
self.0,
to.0,
indices.as_ptr(),
indices.len() as BinaryenIndex,
edge.1,
);
}
}
}
impl Drop for Relooper {
fn drop(&mut self) {
panic!("Relooper dropped without constructing/disposing");
}
}
#[link(name = "binaryen")]
extern "C" {
fn BinaryenModuleRead(data: *const u8, len: usize) -> BinaryenModule;
fn BinaryenModuleCreate() -> BinaryenModule;
fn BinaryenModuleDispose(ptr: BinaryenModule);
fn BinaryenModuleAllocateAndWrite(
ptr: BinaryenModule,
sourceMapUrl: *const c_char,
) -> BinaryenModuleAllocateAndWriteResult;
fn BinaryenGetNumFunctions(ptr: BinaryenModule) -> u32;
fn BinaryenGetFunction(ptr: BinaryenModule, name: *const c_char) -> BinaryenFunction;
fn BinaryenFunctionGetBody(ptr: BinaryenFunction) -> BinaryenExpression;
fn BinaryenFunctionSetBody(ptr: BinaryenFunction, body: BinaryenExpression);
fn BinaryenFunctionGetName(ptr: BinaryenFunction) -> *const c_char;
fn BinaryenFunctionAddVar(ptr: BinaryenFunction, ty: BinaryenType) -> BinaryenIndex;
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 BinaryenGetTableByIndex(ptr: BinaryenModule, index: BinaryenIndex) -> BinaryenTable;
fn BinaryenTableGetName(table: BinaryenTable) -> *const c_char;
fn BinaryenBlockGetNumChildren(ptr: BinaryenExpression) -> u32;
fn BinaryenBlockAppendChild(
ptr: BinaryenExpression,
child: BinaryenExpression,
) -> BinaryenIndex;
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 BinaryenTypeNone() -> BinaryenType;
fn BinaryenTypeInt32() -> BinaryenType;
fn BinaryenTypeInt64() -> BinaryenType;
fn BinaryenTypeFloat32() -> BinaryenType;
fn BinaryenTypeFloat64() -> BinaryenType;
fn BinaryenTypeVec128() -> BinaryenType;
fn BinaryenTypeFuncref() -> BinaryenType;
fn BinaryenTypeCreate(tys: *const BinaryenType, n_tys: BinaryenIndex) -> BinaryenType;
fn BinaryenConst(module: BinaryenModule, lit: BinaryenLiteral) -> BinaryenExpression;
fn BinaryenUnreachable(module: BinaryenModule) -> BinaryenExpression;
fn BinaryenNop(module: BinaryenModule) -> BinaryenExpression;
fn BinaryenLocalGet(
module: BinaryenModule,
local: BinaryenIndex,
ty: BinaryenType,
) -> BinaryenExpression;
fn BinaryenLocalSet(
module: BinaryenModule,
local: BinaryenIndex,
value: BinaryenExpression,
) -> BinaryenExpression;
fn BinaryenLocalTee(
module: BinaryenModule,
local: BinaryenIndex,
value: BinaryenExpression,
ty: BinaryenType,
) -> BinaryenExpression;
fn BinaryenGlobalGet(
module: BinaryenModule,
local: BinaryenIndex,
ty: BinaryenType,
) -> BinaryenExpression;
fn BinaryenGlobalSet(
module: BinaryenModule,
local: BinaryenIndex,
value: BinaryenExpression,
) -> BinaryenExpression;
fn BinaryenSelect(
module: BinaryenModule,
cond: BinaryenExpression,
if_true: BinaryenExpression,
if_false: BinaryenExpression,
ty: BinaryenType,
) -> BinaryenExpression;
fn BinaryenBlock(
module: BinaryenModule,
name: *const c_char,
children: *const BinaryenExpression,
n_children: BinaryenIndex,
ty: BinaryenType,
) -> BinaryenExpression;
fn BinaryenTupleMake(
module: BinaryenModule,
operands: *const BinaryenExpression,
n_operands: BinaryenIndex,
) -> BinaryenExpression;
fn BinaryenReturn(module: BinaryenModule, expr: BinaryenExpression) -> BinaryenExpression;
fn BinaryenDrop(module: BinaryenModule, expr: BinaryenExpression) -> BinaryenExpression;
fn BinaryenUnary(
module: BinaryenModule,
op: BinaryenOp,
arg: BinaryenExpression,
) -> BinaryenExpression;
fn BinaryenBinary(
module: BinaryenModule,
op: BinaryenOp,
left: BinaryenExpression,
right: BinaryenExpression,
) -> BinaryenExpression;
fn BinaryenCall(
module: BinaryenModule,
target: *const c_char,
operands: *const BinaryenExpression,
n_operands: BinaryenIndex,
ret_type: BinaryenType,
) -> BinaryenExpression;
fn BinaryenCallIndirect(
module: BinaryenModule,
table: *const c_char,
target: BinaryenExpression,
operands: *const BinaryenExpression,
n_operands: BinaryenIndex,
param_type: BinaryenType,
ret_type: BinaryenType,
) -> BinaryenExpression;
fn BinaryenLoad(
module: BinaryenModule,
bytes: u32,
signed: bool,
offset: u32,
align: u32,
ty: BinaryenType,
ptr: BinaryenExpression,
) -> BinaryenExpression;
fn BinaryenStore(
module: BinaryenModule,
bytes: u32,
offset: u32,
align: u32,
ptr: BinaryenExpression,
value: BinaryenExpression,
ty: BinaryenType,
) -> BinaryenExpression;
fn BinaryenMemorySize(module: BinaryenModule) -> BinaryenExpression;
fn BinaryenMemoryGrow(module: BinaryenModule, expr: BinaryenExpression) -> BinaryenExpression;
fn BinaryenTableGet(
module: BinaryenModule,
name: *const c_char,
index: BinaryenExpression,
ty: BinaryenType,
) -> BinaryenExpression;
fn BinaryenTableSet(
module: BinaryenModule,
name: *const c_char,
index: BinaryenExpression,
value: BinaryenExpression,
) -> BinaryenExpression;
fn BinaryenTableGrow(
module: BinaryenModule,
name: *const c_char,
value: BinaryenExpression,
delta: BinaryenExpression,
) -> BinaryenExpression;
fn BinaryenTableSize(module: BinaryenModule, name: *const c_char) -> BinaryenExpression;
fn BinaryenAddFunction(
module: BinaryenModule,
name: *const c_char,
params: BinaryenType,
results: BinaryenType,
vars: *const BinaryenType,
n_vars: BinaryenIndex,
body: BinaryenExpression,
) -> BinaryenFunction;
fn BinaryenUndefined() -> BinaryenType;
fn BinaryenLiteralInt32(x: i32) -> BinaryenLiteral;
fn BinaryenLiteralInt64(x: i64) -> BinaryenLiteral;
fn BinaryenLiteralFloat32Bits(x: i32) -> BinaryenLiteral;
fn BinaryenLiteralFloat64Bits(x: i64) -> BinaryenLiteral;
fn RelooperCreate(module: BinaryenModule) -> BinaryenRelooper;
fn RelooperRenderAndDispose(
r: BinaryenRelooper,
entry: BinaryenRelooperBlock,
labelVar: BinaryenIndex,
) -> BinaryenExpression;
fn RelooperAddBlock(r: BinaryenRelooper, code: BinaryenExpression) -> BinaryenRelooperBlock;
fn RelooperAddBranch(
from: BinaryenRelooperBlock,
to: BinaryenRelooperBlock,
cond: BinaryenExpression,
edge_code: BinaryenExpression,
);
fn RelooperAddBlockWithSwitch(
r: BinaryenRelooper,
code: BinaryenExpression,
selector: BinaryenExpression,
) -> BinaryenRelooperBlock;
fn RelooperAddBranchForSwitch(
from: BinaryenRelooperBlock,
to: BinaryenRelooperBlock,
indices: *const BinaryenIndex,
n_indices: BinaryenIndex,
edge_code: BinaryenExpression,
);
fn BinaryenClzInt32() -> BinaryenOp;
fn BinaryenCtzInt32() -> BinaryenOp;
fn BinaryenPopcntInt32() -> BinaryenOp;
fn BinaryenNegFloat32() -> BinaryenOp;
fn BinaryenAbsFloat32() -> BinaryenOp;
fn BinaryenCeilFloat32() -> BinaryenOp;
fn BinaryenFloorFloat32() -> BinaryenOp;
fn BinaryenTruncFloat32() -> BinaryenOp;
fn BinaryenNearestFloat32() -> BinaryenOp;
fn BinaryenSqrtFloat32() -> BinaryenOp;
fn BinaryenEqZInt32() -> BinaryenOp;
fn BinaryenClzInt64() -> BinaryenOp;
fn BinaryenCtzInt64() -> BinaryenOp;
fn BinaryenPopcntInt64() -> BinaryenOp;
fn BinaryenNegFloat64() -> BinaryenOp;
fn BinaryenAbsFloat64() -> BinaryenOp;
fn BinaryenCeilFloat64() -> BinaryenOp;
fn BinaryenFloorFloat64() -> BinaryenOp;
fn BinaryenTruncFloat64() -> BinaryenOp;
fn BinaryenNearestFloat64() -> BinaryenOp;
fn BinaryenSqrtFloat64() -> BinaryenOp;
fn BinaryenEqZInt64() -> BinaryenOp;
fn BinaryenExtendSInt32() -> BinaryenOp;
fn BinaryenExtendUInt32() -> BinaryenOp;
fn BinaryenWrapInt64() -> BinaryenOp;
fn BinaryenTruncSFloat32ToInt32() -> BinaryenOp;
fn BinaryenTruncSFloat32ToInt64() -> BinaryenOp;
fn BinaryenTruncUFloat32ToInt32() -> BinaryenOp;
fn BinaryenTruncUFloat32ToInt64() -> BinaryenOp;
fn BinaryenTruncSFloat64ToInt32() -> BinaryenOp;
fn BinaryenTruncSFloat64ToInt64() -> BinaryenOp;
fn BinaryenTruncUFloat64ToInt32() -> BinaryenOp;
fn BinaryenTruncUFloat64ToInt64() -> BinaryenOp;
fn BinaryenReinterpretFloat32() -> BinaryenOp;
fn BinaryenReinterpretFloat64() -> BinaryenOp;
fn BinaryenConvertSInt32ToFloat32() -> BinaryenOp;
fn BinaryenConvertSInt32ToFloat64() -> BinaryenOp;
fn BinaryenConvertUInt32ToFloat32() -> BinaryenOp;
fn BinaryenConvertUInt32ToFloat64() -> BinaryenOp;
fn BinaryenConvertSInt64ToFloat32() -> BinaryenOp;
fn BinaryenConvertSInt64ToFloat64() -> BinaryenOp;
fn BinaryenConvertUInt64ToFloat32() -> BinaryenOp;
fn BinaryenConvertUInt64ToFloat64() -> BinaryenOp;
fn BinaryenPromoteFloat32() -> BinaryenOp;
fn BinaryenDemoteFloat64() -> BinaryenOp;
fn BinaryenReinterpretInt32() -> BinaryenOp;
fn BinaryenReinterpretInt64() -> BinaryenOp;
fn BinaryenExtendS8Int32() -> BinaryenOp;
fn BinaryenExtendS16Int32() -> BinaryenOp;
fn BinaryenExtendS8Int64() -> BinaryenOp;
fn BinaryenExtendS16Int64() -> BinaryenOp;
fn BinaryenExtendS32Int64() -> BinaryenOp;
fn BinaryenAddInt32() -> BinaryenOp;
fn BinaryenSubInt32() -> BinaryenOp;
fn BinaryenMulInt32() -> BinaryenOp;
fn BinaryenDivSInt32() -> BinaryenOp;
fn BinaryenDivUInt32() -> BinaryenOp;
fn BinaryenRemSInt32() -> BinaryenOp;
fn BinaryenRemUInt32() -> BinaryenOp;
fn BinaryenAndInt32() -> BinaryenOp;
fn BinaryenOrInt32() -> BinaryenOp;
fn BinaryenXorInt32() -> BinaryenOp;
fn BinaryenShlInt32() -> BinaryenOp;
fn BinaryenShrUInt32() -> BinaryenOp;
fn BinaryenShrSInt32() -> BinaryenOp;
fn BinaryenRotLInt32() -> BinaryenOp;
fn BinaryenRotRInt32() -> BinaryenOp;
fn BinaryenEqInt32() -> BinaryenOp;
fn BinaryenNeInt32() -> BinaryenOp;
fn BinaryenLtSInt32() -> BinaryenOp;
fn BinaryenLtUInt32() -> BinaryenOp;
fn BinaryenLeSInt32() -> BinaryenOp;
fn BinaryenLeUInt32() -> BinaryenOp;
fn BinaryenGtSInt32() -> BinaryenOp;
fn BinaryenGtUInt32() -> BinaryenOp;
fn BinaryenGeSInt32() -> BinaryenOp;
fn BinaryenGeUInt32() -> BinaryenOp;
fn BinaryenAddInt64() -> BinaryenOp;
fn BinaryenSubInt64() -> BinaryenOp;
fn BinaryenMulInt64() -> BinaryenOp;
fn BinaryenDivSInt64() -> BinaryenOp;
fn BinaryenDivUInt64() -> BinaryenOp;
fn BinaryenRemSInt64() -> BinaryenOp;
fn BinaryenRemUInt64() -> BinaryenOp;
fn BinaryenAndInt64() -> BinaryenOp;
fn BinaryenOrInt64() -> BinaryenOp;
fn BinaryenXorInt64() -> BinaryenOp;
fn BinaryenShlInt64() -> BinaryenOp;
fn BinaryenShrUInt64() -> BinaryenOp;
fn BinaryenShrSInt64() -> BinaryenOp;
fn BinaryenRotLInt64() -> BinaryenOp;
fn BinaryenRotRInt64() -> BinaryenOp;
fn BinaryenEqInt64() -> BinaryenOp;
fn BinaryenNeInt64() -> BinaryenOp;
fn BinaryenLtSInt64() -> BinaryenOp;
fn BinaryenLtUInt64() -> BinaryenOp;
fn BinaryenLeSInt64() -> BinaryenOp;
fn BinaryenLeUInt64() -> BinaryenOp;
fn BinaryenGtSInt64() -> BinaryenOp;
fn BinaryenGtUInt64() -> BinaryenOp;
fn BinaryenGeSInt64() -> BinaryenOp;
fn BinaryenGeUInt64() -> BinaryenOp;
fn BinaryenAddFloat32() -> BinaryenOp;
fn BinaryenSubFloat32() -> BinaryenOp;
fn BinaryenMulFloat32() -> BinaryenOp;
fn BinaryenDivFloat32() -> BinaryenOp;
fn BinaryenCopySignFloat32() -> BinaryenOp;
fn BinaryenMinFloat32() -> BinaryenOp;
fn BinaryenMaxFloat32() -> BinaryenOp;
fn BinaryenEqFloat32() -> BinaryenOp;
fn BinaryenNeFloat32() -> BinaryenOp;
fn BinaryenLtFloat32() -> BinaryenOp;
fn BinaryenLeFloat32() -> BinaryenOp;
fn BinaryenGtFloat32() -> BinaryenOp;
fn BinaryenGeFloat32() -> BinaryenOp;
fn BinaryenAddFloat64() -> BinaryenOp;
fn BinaryenSubFloat64() -> BinaryenOp;
fn BinaryenMulFloat64() -> BinaryenOp;
fn BinaryenDivFloat64() -> BinaryenOp;
fn BinaryenCopySignFloat64() -> BinaryenOp;
fn BinaryenMinFloat64() -> BinaryenOp;
fn BinaryenMaxFloat64() -> BinaryenOp;
fn BinaryenEqFloat64() -> BinaryenOp;
fn BinaryenNeFloat64() -> BinaryenOp;
fn BinaryenLtFloat64() -> BinaryenOp;
fn BinaryenLeFloat64() -> BinaryenOp;
fn BinaryenGtFloat64() -> BinaryenOp;
fn BinaryenGeFloat64() -> BinaryenOp;
fn BinaryenAtomicRMWAdd() -> BinaryenOp;
fn BinaryenAtomicRMWSub() -> BinaryenOp;
fn BinaryenAtomicRMWAnd() -> BinaryenOp;
fn BinaryenAtomicRMWOr() -> BinaryenOp;
fn BinaryenAtomicRMWXor() -> BinaryenOp;
fn BinaryenAtomicRMWXchg() -> BinaryenOp;
fn BinaryenTruncSatSFloat32ToInt32() -> BinaryenOp;
fn BinaryenTruncSatSFloat32ToInt64() -> BinaryenOp;
fn BinaryenTruncSatUFloat32ToInt32() -> BinaryenOp;
fn BinaryenTruncSatUFloat32ToInt64() -> BinaryenOp;
fn BinaryenTruncSatSFloat64ToInt32() -> BinaryenOp;
fn BinaryenTruncSatSFloat64ToInt64() -> BinaryenOp;
fn BinaryenTruncSatUFloat64ToInt32() -> BinaryenOp;
fn BinaryenTruncSatUFloat64ToInt64() -> BinaryenOp;
fn BinaryenSplatVecI8x16() -> BinaryenOp;
fn BinaryenExtractLaneSVecI8x16() -> BinaryenOp;
fn BinaryenExtractLaneUVecI8x16() -> BinaryenOp;
fn BinaryenReplaceLaneVecI8x16() -> BinaryenOp;
fn BinaryenSplatVecI16x8() -> BinaryenOp;
fn BinaryenExtractLaneSVecI16x8() -> BinaryenOp;
fn BinaryenExtractLaneUVecI16x8() -> BinaryenOp;
fn BinaryenReplaceLaneVecI16x8() -> BinaryenOp;
fn BinaryenSplatVecI32x4() -> BinaryenOp;
fn BinaryenExtractLaneVecI32x4() -> BinaryenOp;
fn BinaryenReplaceLaneVecI32x4() -> BinaryenOp;
fn BinaryenSplatVecI64x2() -> BinaryenOp;
fn BinaryenExtractLaneVecI64x2() -> BinaryenOp;
fn BinaryenReplaceLaneVecI64x2() -> BinaryenOp;
fn BinaryenSplatVecF32x4() -> BinaryenOp;
fn BinaryenExtractLaneVecF32x4() -> BinaryenOp;
fn BinaryenReplaceLaneVecF32x4() -> BinaryenOp;
fn BinaryenSplatVecF64x2() -> BinaryenOp;
fn BinaryenExtractLaneVecF64x2() -> BinaryenOp;
fn BinaryenReplaceLaneVecF64x2() -> BinaryenOp;
fn BinaryenEqVecI8x16() -> BinaryenOp;
fn BinaryenNeVecI8x16() -> BinaryenOp;
fn BinaryenLtSVecI8x16() -> BinaryenOp;
fn BinaryenLtUVecI8x16() -> BinaryenOp;
fn BinaryenGtSVecI8x16() -> BinaryenOp;
fn BinaryenGtUVecI8x16() -> BinaryenOp;
fn BinaryenLeSVecI8x16() -> BinaryenOp;
fn BinaryenLeUVecI8x16() -> BinaryenOp;
fn BinaryenGeSVecI8x16() -> BinaryenOp;
fn BinaryenGeUVecI8x16() -> BinaryenOp;
fn BinaryenEqVecI16x8() -> BinaryenOp;
fn BinaryenNeVecI16x8() -> BinaryenOp;
fn BinaryenLtSVecI16x8() -> BinaryenOp;
fn BinaryenLtUVecI16x8() -> BinaryenOp;
fn BinaryenGtSVecI16x8() -> BinaryenOp;
fn BinaryenGtUVecI16x8() -> BinaryenOp;
fn BinaryenLeSVecI16x8() -> BinaryenOp;
fn BinaryenLeUVecI16x8() -> BinaryenOp;
fn BinaryenGeSVecI16x8() -> BinaryenOp;
fn BinaryenGeUVecI16x8() -> BinaryenOp;
fn BinaryenEqVecI32x4() -> BinaryenOp;
fn BinaryenNeVecI32x4() -> BinaryenOp;
fn BinaryenLtSVecI32x4() -> BinaryenOp;
fn BinaryenLtUVecI32x4() -> BinaryenOp;
fn BinaryenGtSVecI32x4() -> BinaryenOp;
fn BinaryenGtUVecI32x4() -> BinaryenOp;
fn BinaryenLeSVecI32x4() -> BinaryenOp;
fn BinaryenLeUVecI32x4() -> BinaryenOp;
fn BinaryenGeSVecI32x4() -> BinaryenOp;
fn BinaryenGeUVecI32x4() -> BinaryenOp;
fn BinaryenEqVecI64x2() -> BinaryenOp;
fn BinaryenNeVecI64x2() -> BinaryenOp;
fn BinaryenLtSVecI64x2() -> BinaryenOp;
fn BinaryenGtSVecI64x2() -> BinaryenOp;
fn BinaryenLeSVecI64x2() -> BinaryenOp;
fn BinaryenGeSVecI64x2() -> BinaryenOp;
fn BinaryenEqVecF32x4() -> BinaryenOp;
fn BinaryenNeVecF32x4() -> BinaryenOp;
fn BinaryenLtVecF32x4() -> BinaryenOp;
fn BinaryenGtVecF32x4() -> BinaryenOp;
fn BinaryenLeVecF32x4() -> BinaryenOp;
fn BinaryenGeVecF32x4() -> BinaryenOp;
fn BinaryenEqVecF64x2() -> BinaryenOp;
fn BinaryenNeVecF64x2() -> BinaryenOp;
fn BinaryenLtVecF64x2() -> BinaryenOp;
fn BinaryenGtVecF64x2() -> BinaryenOp;
fn BinaryenLeVecF64x2() -> BinaryenOp;
fn BinaryenGeVecF64x2() -> BinaryenOp;
fn BinaryenNotVec128() -> BinaryenOp;
fn BinaryenAndVec128() -> BinaryenOp;
fn BinaryenOrVec128() -> BinaryenOp;
fn BinaryenXorVec128() -> BinaryenOp;
fn BinaryenAndNotVec128() -> BinaryenOp;
fn BinaryenBitselectVec128() -> BinaryenOp;
fn BinaryenAnyTrueVec128() -> BinaryenOp;
fn BinaryenPopcntVecI8x16() -> BinaryenOp;
fn BinaryenAbsVecI8x16() -> BinaryenOp;
fn BinaryenNegVecI8x16() -> BinaryenOp;
fn BinaryenAllTrueVecI8x16() -> BinaryenOp;
fn BinaryenBitmaskVecI8x16() -> BinaryenOp;
fn BinaryenShlVecI8x16() -> BinaryenOp;
fn BinaryenShrSVecI8x16() -> BinaryenOp;
fn BinaryenShrUVecI8x16() -> BinaryenOp;
fn BinaryenAddVecI8x16() -> BinaryenOp;
fn BinaryenAddSatSVecI8x16() -> BinaryenOp;
fn BinaryenAddSatUVecI8x16() -> BinaryenOp;
fn BinaryenSubVecI8x16() -> BinaryenOp;
fn BinaryenSubSatSVecI8x16() -> BinaryenOp;
fn BinaryenSubSatUVecI8x16() -> BinaryenOp;
fn BinaryenMinSVecI8x16() -> BinaryenOp;
fn BinaryenMinUVecI8x16() -> BinaryenOp;
fn BinaryenMaxSVecI8x16() -> BinaryenOp;
fn BinaryenMaxUVecI8x16() -> BinaryenOp;
fn BinaryenAvgrUVecI8x16() -> BinaryenOp;
fn BinaryenAbsVecI16x8() -> BinaryenOp;
fn BinaryenNegVecI16x8() -> BinaryenOp;
fn BinaryenAllTrueVecI16x8() -> BinaryenOp;
fn BinaryenBitmaskVecI16x8() -> BinaryenOp;
fn BinaryenShlVecI16x8() -> BinaryenOp;
fn BinaryenShrSVecI16x8() -> BinaryenOp;
fn BinaryenShrUVecI16x8() -> BinaryenOp;
fn BinaryenAddVecI16x8() -> BinaryenOp;
fn BinaryenAddSatSVecI16x8() -> BinaryenOp;
fn BinaryenAddSatUVecI16x8() -> BinaryenOp;
fn BinaryenSubVecI16x8() -> BinaryenOp;
fn BinaryenSubSatSVecI16x8() -> BinaryenOp;
fn BinaryenSubSatUVecI16x8() -> BinaryenOp;
fn BinaryenMulVecI16x8() -> BinaryenOp;
fn BinaryenMinSVecI16x8() -> BinaryenOp;
fn BinaryenMinUVecI16x8() -> BinaryenOp;
fn BinaryenMaxSVecI16x8() -> BinaryenOp;
fn BinaryenMaxUVecI16x8() -> BinaryenOp;
fn BinaryenAvgrUVecI16x8() -> BinaryenOp;
fn BinaryenQ15MulrSatSVecI16x8() -> BinaryenOp;
fn BinaryenExtMulLowSVecI16x8() -> BinaryenOp;
fn BinaryenExtMulHighSVecI16x8() -> BinaryenOp;
fn BinaryenExtMulLowUVecI16x8() -> BinaryenOp;
fn BinaryenExtMulHighUVecI16x8() -> BinaryenOp;
fn BinaryenAbsVecI32x4() -> BinaryenOp;
fn BinaryenNegVecI32x4() -> BinaryenOp;
fn BinaryenAllTrueVecI32x4() -> BinaryenOp;
fn BinaryenBitmaskVecI32x4() -> BinaryenOp;
fn BinaryenShlVecI32x4() -> BinaryenOp;
fn BinaryenShrSVecI32x4() -> BinaryenOp;
fn BinaryenShrUVecI32x4() -> BinaryenOp;
fn BinaryenAddVecI32x4() -> BinaryenOp;
fn BinaryenSubVecI32x4() -> BinaryenOp;
fn BinaryenMulVecI32x4() -> BinaryenOp;
fn BinaryenMinSVecI32x4() -> BinaryenOp;
fn BinaryenMinUVecI32x4() -> BinaryenOp;
fn BinaryenMaxSVecI32x4() -> BinaryenOp;
fn BinaryenMaxUVecI32x4() -> BinaryenOp;
fn BinaryenDotSVecI16x8ToVecI32x4() -> BinaryenOp;
fn BinaryenExtMulLowSVecI32x4() -> BinaryenOp;
fn BinaryenExtMulHighSVecI32x4() -> BinaryenOp;
fn BinaryenExtMulLowUVecI32x4() -> BinaryenOp;
fn BinaryenExtMulHighUVecI32x4() -> BinaryenOp;
fn BinaryenAbsVecI64x2() -> BinaryenOp;
fn BinaryenNegVecI64x2() -> BinaryenOp;
fn BinaryenAllTrueVecI64x2() -> BinaryenOp;
fn BinaryenBitmaskVecI64x2() -> BinaryenOp;
fn BinaryenShlVecI64x2() -> BinaryenOp;
fn BinaryenShrSVecI64x2() -> BinaryenOp;
fn BinaryenShrUVecI64x2() -> BinaryenOp;
fn BinaryenAddVecI64x2() -> BinaryenOp;
fn BinaryenSubVecI64x2() -> BinaryenOp;
fn BinaryenMulVecI64x2() -> BinaryenOp;
fn BinaryenExtMulLowSVecI64x2() -> BinaryenOp;
fn BinaryenExtMulHighSVecI64x2() -> BinaryenOp;
fn BinaryenExtMulLowUVecI64x2() -> BinaryenOp;
fn BinaryenExtMulHighUVecI64x2() -> BinaryenOp;
fn BinaryenAbsVecF32x4() -> BinaryenOp;
fn BinaryenNegVecF32x4() -> BinaryenOp;
fn BinaryenSqrtVecF32x4() -> BinaryenOp;
fn BinaryenAddVecF32x4() -> BinaryenOp;
fn BinaryenSubVecF32x4() -> BinaryenOp;
fn BinaryenMulVecF32x4() -> BinaryenOp;
fn BinaryenDivVecF32x4() -> BinaryenOp;
fn BinaryenMinVecF32x4() -> BinaryenOp;
fn BinaryenMaxVecF32x4() -> BinaryenOp;
fn BinaryenPMinVecF32x4() -> BinaryenOp;
fn BinaryenPMaxVecF32x4() -> BinaryenOp;
fn BinaryenCeilVecF32x4() -> BinaryenOp;
fn BinaryenFloorVecF32x4() -> BinaryenOp;
fn BinaryenTruncVecF32x4() -> BinaryenOp;
fn BinaryenNearestVecF32x4() -> BinaryenOp;
fn BinaryenAbsVecF64x2() -> BinaryenOp;
fn BinaryenNegVecF64x2() -> BinaryenOp;
fn BinaryenSqrtVecF64x2() -> BinaryenOp;
fn BinaryenAddVecF64x2() -> BinaryenOp;
fn BinaryenSubVecF64x2() -> BinaryenOp;
fn BinaryenMulVecF64x2() -> BinaryenOp;
fn BinaryenDivVecF64x2() -> BinaryenOp;
fn BinaryenMinVecF64x2() -> BinaryenOp;
fn BinaryenMaxVecF64x2() -> BinaryenOp;
fn BinaryenPMinVecF64x2() -> BinaryenOp;
fn BinaryenPMaxVecF64x2() -> BinaryenOp;
fn BinaryenCeilVecF64x2() -> BinaryenOp;
fn BinaryenFloorVecF64x2() -> BinaryenOp;
fn BinaryenTruncVecF64x2() -> BinaryenOp;
fn BinaryenNearestVecF64x2() -> BinaryenOp;
fn BinaryenExtAddPairwiseSVecI8x16ToI16x8() -> BinaryenOp;
fn BinaryenExtAddPairwiseUVecI8x16ToI16x8() -> BinaryenOp;
fn BinaryenExtAddPairwiseSVecI16x8ToI32x4() -> BinaryenOp;
fn BinaryenExtAddPairwiseUVecI16x8ToI32x4() -> BinaryenOp;
fn BinaryenTruncSatSVecF32x4ToVecI32x4() -> BinaryenOp;
fn BinaryenTruncSatUVecF32x4ToVecI32x4() -> BinaryenOp;
fn BinaryenConvertSVecI32x4ToVecF32x4() -> BinaryenOp;
fn BinaryenConvertUVecI32x4ToVecF32x4() -> BinaryenOp;
fn BinaryenLoad8SplatVec128() -> BinaryenOp;
fn BinaryenLoad16SplatVec128() -> BinaryenOp;
fn BinaryenLoad32SplatVec128() -> BinaryenOp;
fn BinaryenLoad64SplatVec128() -> BinaryenOp;
fn BinaryenLoad8x8SVec128() -> BinaryenOp;
fn BinaryenLoad8x8UVec128() -> BinaryenOp;
fn BinaryenLoad16x4SVec128() -> BinaryenOp;
fn BinaryenLoad16x4UVec128() -> BinaryenOp;
fn BinaryenLoad32x2SVec128() -> BinaryenOp;
fn BinaryenLoad32x2UVec128() -> BinaryenOp;
fn BinaryenLoad32ZeroVec128() -> BinaryenOp;
fn BinaryenLoad64ZeroVec128() -> BinaryenOp;
fn BinaryenLoad8LaneVec128() -> BinaryenOp;
fn BinaryenLoad16LaneVec128() -> BinaryenOp;
fn BinaryenLoad32LaneVec128() -> BinaryenOp;
fn BinaryenLoad64LaneVec128() -> BinaryenOp;
fn BinaryenStore8LaneVec128() -> BinaryenOp;
fn BinaryenStore16LaneVec128() -> BinaryenOp;
fn BinaryenStore32LaneVec128() -> BinaryenOp;
fn BinaryenStore64LaneVec128() -> BinaryenOp;
fn BinaryenNarrowSVecI16x8ToVecI8x16() -> BinaryenOp;
fn BinaryenNarrowUVecI16x8ToVecI8x16() -> BinaryenOp;
fn BinaryenNarrowSVecI32x4ToVecI16x8() -> BinaryenOp;
fn BinaryenNarrowUVecI32x4ToVecI16x8() -> BinaryenOp;
fn BinaryenExtendLowSVecI8x16ToVecI16x8() -> BinaryenOp;
fn BinaryenExtendHighSVecI8x16ToVecI16x8() -> BinaryenOp;
fn BinaryenExtendLowUVecI8x16ToVecI16x8() -> BinaryenOp;
fn BinaryenExtendHighUVecI8x16ToVecI16x8() -> BinaryenOp;
fn BinaryenExtendLowSVecI16x8ToVecI32x4() -> BinaryenOp;
fn BinaryenExtendHighSVecI16x8ToVecI32x4() -> BinaryenOp;
fn BinaryenExtendLowUVecI16x8ToVecI32x4() -> BinaryenOp;
fn BinaryenExtendHighUVecI16x8ToVecI32x4() -> BinaryenOp;
fn BinaryenExtendLowSVecI32x4ToVecI64x2() -> BinaryenOp;
fn BinaryenExtendHighSVecI32x4ToVecI64x2() -> BinaryenOp;
fn BinaryenExtendLowUVecI32x4ToVecI64x2() -> BinaryenOp;
fn BinaryenExtendHighUVecI32x4ToVecI64x2() -> BinaryenOp;
fn BinaryenConvertLowSVecI32x4ToVecF64x2() -> BinaryenOp;
fn BinaryenConvertLowUVecI32x4ToVecF64x2() -> BinaryenOp;
fn BinaryenTruncSatZeroSVecF64x2ToVecI32x4() -> BinaryenOp;
fn BinaryenTruncSatZeroUVecF64x2ToVecI32x4() -> BinaryenOp;
fn BinaryenDemoteZeroVecF64x2ToVecF32x4() -> BinaryenOp;
fn BinaryenPromoteLowVecF32x4ToVecF64x2() -> BinaryenOp;
fn BinaryenSwizzleVec8x16() -> BinaryenOp;
fn BinaryenRefIsNull() -> BinaryenOp;
fn BinaryenRefIsFunc() -> BinaryenOp;
fn BinaryenRefIsData() -> BinaryenOp;
fn BinaryenRefIsI31() -> BinaryenOp;
fn BinaryenRefAsNonNull() -> BinaryenOp;
fn BinaryenRefAsFunc() -> BinaryenOp;
fn BinaryenRefAsData() -> BinaryenOp;
fn BinaryenRefAsI31() -> BinaryenOp;
fn BinaryenAddGlobal(
module: BinaryenModule,
name: *const c_char,
ty: BinaryenType,
mutable: bool,
init: BinaryenExpression,
) -> BinaryenGlobal;
fn BinaryenGetNumGlobals(module: BinaryenModule) -> BinaryenIndex;
fn BinaryenAddTable(
module: BinaryenModule,
name: *const c_char,
initial: BinaryenIndex,
max: BinaryenIndex,
ty: BinaryenType,
) -> BinaryenTable;
fn BinaryenGetNumTables(module: BinaryenModule) -> BinaryenIndex;
fn BinaryenAddActiveElementSegment(
module: BinaryenModule,
table: *const c_char,
name: *const c_char,
func_names: *const *const c_char,
num_funcs: BinaryenIndex,
offset: BinaryenExpression,
) -> BinaryenElementSegment;
fn BinaryenSetMemory(
module: BinaryenModule,
init: BinaryenIndex,
max: BinaryenIndex,
export_name: *const c_char,
segments: *const *const c_char,
seg_passive: *const bool,
seg_offsets: *const BinaryenExpression,
sizes: *const BinaryenIndex,
n_segments: BinaryenIndex,
shared: bool,
);
fn BinaryenAddTableImport(
module: BinaryenModule,
name: *const c_char,
extern_module: *const c_char,
extern_name: *const c_char,
);
fn BinaryenAddMemoryImport(
module: BinaryenModule,
name: *const c_char,
extern_module: *const c_char,
extern_name: *const c_char,
);
fn BinaryenAddGlobalImport(
module: BinaryenModule,
name: *const c_char,
extern_module: *const c_char,
extern_name: *const c_char,
ty: BinaryenType,
mutable: bool,
);
fn BinaryenAddFunctionImport(
module: BinaryenModule,
name: *const c_char,
extern_module: *const c_char,
extern_name: *const c_char,
params: BinaryenType,
results: BinaryenType,
);
fn BinaryenGlobalGetName(global: BinaryenGlobal) -> *const c_char;
fn BinaryenGetGlobalByIndex(module: BinaryenModule, index: BinaryenIndex) -> BinaryenGlobal;
fn BinaryenAddTableExport(
module: BinaryenModule,
internal: *const c_char,
external: *const c_char,
);
fn BinaryenAddFunctionExport(
module: BinaryenModule,
internal: *const c_char,
external: *const c_char,
);
fn BinaryenAddGlobalExport(
module: BinaryenModule,
internal: *const c_char,
external: *const c_char,
);
fn BinaryenAddMemoryExport(
module: BinaryenModule,
internal: *const c_char,
external: *const c_char,
);
}
#[repr(C)]
struct BinaryenLiteral {
_pad0: usize,
_pad1: [u8; 16],
}
type BinaryenOp = i32;