1656 lines
45 KiB
Rust
1656 lines
45 KiB
Rust
//! This file defines the extern "C" API, which is compatible with the
|
|
//! [Wasm C API](https://github.com/WebAssembly/wasm-c-api).
|
|
|
|
#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
|
|
|
|
// TODO complete the C API
|
|
|
|
use super::{
|
|
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
|
|
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Name, Store,
|
|
Table, TableType, Trap, Val, ValType,
|
|
};
|
|
use alloc::boxed::Box;
|
|
use alloc::rc::Rc;
|
|
use core::mem;
|
|
use core::ptr;
|
|
use core::slice;
|
|
|
|
macro_rules! declare_vec {
|
|
($name:ident, $elem_ty:path) => {
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct $name {
|
|
pub size: usize,
|
|
pub data: *mut $elem_ty,
|
|
}
|
|
|
|
impl $name {
|
|
#[allow(dead_code)]
|
|
fn set_from_slice(&mut self, source: &[$elem_ty]) {
|
|
let mut buffer = Vec::with_capacity(source.len());
|
|
buffer.extend_from_slice(source);
|
|
assert!(buffer.len() == buffer.capacity());
|
|
self.size = buffer.len();
|
|
self.data = buffer.as_mut_ptr();
|
|
mem::forget(buffer);
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn set_buffer(&mut self, mut buffer: Vec<$elem_ty>) {
|
|
assert!(buffer.len() == buffer.capacity());
|
|
self.size = buffer.len();
|
|
self.data = buffer.as_mut_ptr();
|
|
mem::forget(buffer);
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn set_uninitialized(&mut self, size: usize) {
|
|
let mut buffer = vec![Default::default(); size];
|
|
self.size = size;
|
|
self.data = buffer.as_mut_ptr();
|
|
mem::forget(buffer);
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn uninitialize(&mut self) {
|
|
let _ = unsafe { Vec::from_raw_parts(self.data, self.size, self.size) };
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn as_slice(&self) -> &[$elem_ty] {
|
|
unsafe { slice::from_raw_parts(self.data as *const $elem_ty, self.size) }
|
|
}
|
|
}
|
|
|
|
impl From<Vec<$elem_ty>> for $name {
|
|
fn from(mut vec: Vec<$elem_ty>) -> Self {
|
|
assert!(vec.len() == vec.capacity());
|
|
let result = $name {
|
|
size: vec.len(),
|
|
data: vec.as_mut_ptr(),
|
|
};
|
|
mem::forget(vec);
|
|
result
|
|
}
|
|
}
|
|
|
|
impl Drop for $name {
|
|
fn drop(&mut self) {
|
|
self.uninitialize();
|
|
}
|
|
}
|
|
};
|
|
|
|
($name:ident, *mut $elem_ty:path) => {
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct $name {
|
|
pub size: usize,
|
|
pub data: *mut *mut $elem_ty,
|
|
}
|
|
|
|
impl $name {
|
|
#[allow(dead_code)]
|
|
fn set_from_slice(&mut self, source: &[*mut $elem_ty]) {
|
|
let mut buffer = Vec::with_capacity(source.len());
|
|
buffer.extend_from_slice(source);
|
|
assert!(buffer.len() == buffer.capacity());
|
|
self.size = buffer.len();
|
|
self.data = buffer.as_mut_ptr();
|
|
mem::forget(buffer);
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn set_buffer(&mut self, mut buffer: Vec<*mut $elem_ty>) {
|
|
assert!(buffer.len() == buffer.capacity());
|
|
self.size = buffer.len();
|
|
self.data = buffer.as_mut_ptr();
|
|
mem::forget(buffer);
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn set_uninitialized(&mut self, size: usize) {
|
|
let mut buffer = vec![ptr::null_mut(); size];
|
|
self.size = size;
|
|
self.data = buffer.as_mut_ptr();
|
|
mem::forget(buffer);
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn uninitialize(&mut self) {
|
|
for element in unsafe { Vec::from_raw_parts(self.data, self.size, self.size) } {
|
|
let _ = unsafe { Box::from_raw(element) };
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn as_slice(&self) -> &[$elem_ty] {
|
|
unsafe { slice::from_raw_parts(self.data as *const $elem_ty, self.size) }
|
|
}
|
|
}
|
|
|
|
impl From<Vec<*mut $elem_ty>> for $name {
|
|
fn from(mut vec: Vec<*mut $elem_ty>) -> Self {
|
|
assert!(vec.len() == vec.capacity());
|
|
let result = $name {
|
|
size: vec.len(),
|
|
data: vec.as_mut_ptr(),
|
|
};
|
|
mem::forget(vec);
|
|
result
|
|
}
|
|
}
|
|
|
|
impl Drop for $name {
|
|
fn drop(&mut self) {
|
|
self.uninitialize();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
pub type float32_t = f32;
|
|
pub type float64_t = f64;
|
|
pub type wasm_byte_t = u8;
|
|
|
|
declare_vec!(wasm_byte_vec_t, wasm_byte_t);
|
|
|
|
pub type wasm_name_t = wasm_byte_vec_t;
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_config_t {
|
|
_unused: [u8; 0],
|
|
}
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_engine_t {
|
|
engine: HostRef<Engine>,
|
|
}
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_store_t {
|
|
store: HostRef<Store>,
|
|
}
|
|
#[doc = ""]
|
|
pub type wasm_mutability_t = u8;
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_limits_t {
|
|
pub min: u32,
|
|
pub max: u32,
|
|
}
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_valtype_t {
|
|
ty: ValType,
|
|
}
|
|
|
|
declare_vec!(wasm_valtype_vec_t, *mut wasm_valtype_t);
|
|
|
|
pub type wasm_valkind_t = u8;
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_functype_t {
|
|
functype: FuncType,
|
|
params_cache: Option<wasm_valtype_vec_t>,
|
|
returns_cache: Option<wasm_valtype_vec_t>,
|
|
}
|
|
|
|
declare_vec!(wasm_functype_vec_t, *mut wasm_functype_t);
|
|
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_globaltype_t {
|
|
globaltype: GlobalType,
|
|
content_cache: Option<wasm_valtype_t>,
|
|
}
|
|
|
|
declare_vec!(wasm_globaltype_vec_t, *mut wasm_globaltype_t);
|
|
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_tabletype_t {
|
|
tabletype: TableType,
|
|
element_cache: Option<wasm_valtype_t>,
|
|
limits_cache: Option<wasm_limits_t>,
|
|
}
|
|
|
|
declare_vec!(wasm_tabletype_vec_t, *mut wasm_tabletype_t);
|
|
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_memorytype_t {
|
|
memorytype: MemoryType,
|
|
limits_cache: Option<wasm_limits_t>,
|
|
}
|
|
|
|
declare_vec!(wasm_memorytype_vec_t, *mut wasm_memorytype_t);
|
|
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_externtype_t {
|
|
ty: ExternType,
|
|
cache: wasm_externtype_t_type_cache,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
enum wasm_externtype_t_type_cache {
|
|
Empty,
|
|
Func(wasm_functype_t),
|
|
Global(wasm_globaltype_t),
|
|
Memory(wasm_memorytype_t),
|
|
Table(wasm_tabletype_t),
|
|
}
|
|
|
|
declare_vec!(wasm_externtype_vec_t, *mut wasm_externtype_t);
|
|
|
|
pub type wasm_externkind_t = u8;
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_importtype_t {
|
|
ty: ImportType,
|
|
module_cache: Option<wasm_name_t>,
|
|
name_cache: Option<wasm_name_t>,
|
|
}
|
|
|
|
declare_vec!(wasm_importtype_vec_t, *mut wasm_importtype_t);
|
|
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_exporttype_t {
|
|
ty: ExportType,
|
|
name_cache: Option<wasm_name_t>,
|
|
type_cache: Option<wasm_externtype_t>,
|
|
}
|
|
|
|
declare_vec!(wasm_exporttype_vec_t, *mut wasm_exporttype_t);
|
|
|
|
#[doc = ""]
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_ref_t {
|
|
r: AnyRef,
|
|
}
|
|
#[repr(C)]
|
|
#[derive(Copy, Clone)]
|
|
pub struct wasm_val_t {
|
|
pub kind: wasm_valkind_t,
|
|
pub of: wasm_val_t__bindgen_ty_1,
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Copy, Clone)]
|
|
pub union wasm_val_t__bindgen_ty_1 {
|
|
pub i32: i32,
|
|
pub i64: i64,
|
|
pub u32: u32,
|
|
pub u64: u64,
|
|
pub f32: float32_t,
|
|
pub f64: float64_t,
|
|
pub ref_: *mut wasm_ref_t,
|
|
_bindgen_union_align: u64,
|
|
}
|
|
|
|
impl Default for wasm_val_t {
|
|
fn default() -> Self {
|
|
wasm_val_t {
|
|
kind: 0,
|
|
of: wasm_val_t__bindgen_ty_1 { i32: 0 },
|
|
}
|
|
}
|
|
}
|
|
|
|
declare_vec!(wasm_val_vec_t, wasm_val_t);
|
|
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_frame_t {
|
|
_unused: [u8; 0],
|
|
}
|
|
|
|
declare_vec!(wasm_frame_vec_t, *mut wasm_frame_t);
|
|
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_instance_t {
|
|
instance: HostRef<Instance>,
|
|
}
|
|
pub type wasm_message_t = wasm_name_t;
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_trap_t {
|
|
trap: HostRef<Trap>,
|
|
}
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_foreign_t {
|
|
_unused: [u8; 0],
|
|
}
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_module_t {
|
|
module: HostRef<Module>,
|
|
imports: Vec<wasm_importtype_t>,
|
|
exports: Vec<wasm_exporttype_t>,
|
|
}
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_shared_module_t {
|
|
_unused: [u8; 0],
|
|
}
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_func_t {
|
|
func: HostRef<Func>,
|
|
ext: Option<Box<wasm_extern_t>>,
|
|
}
|
|
pub type wasm_func_callback_t = ::core::option::Option<
|
|
unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t,
|
|
>;
|
|
pub type wasm_func_callback_with_env_t = ::core::option::Option<
|
|
unsafe extern "C" fn(
|
|
env: *mut ::core::ffi::c_void,
|
|
args: *const wasm_val_t,
|
|
results: *mut wasm_val_t,
|
|
) -> *mut wasm_trap_t,
|
|
>;
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_global_t {
|
|
global: HostRef<Global>,
|
|
ext: Option<Box<wasm_extern_t>>,
|
|
}
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_table_t {
|
|
table: HostRef<Table>,
|
|
ext: Option<Box<wasm_extern_t>>,
|
|
}
|
|
pub type wasm_table_size_t = u32;
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_memory_t {
|
|
memory: HostRef<Memory>,
|
|
ext: Option<Box<wasm_extern_t>>,
|
|
}
|
|
pub type wasm_memory_pages_t = u32;
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct wasm_extern_t {
|
|
ext: Extern,
|
|
cache: wasm_extern_t_type_cache,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
enum wasm_extern_t_type_cache {
|
|
Empty,
|
|
Func(wasm_func_t),
|
|
Global(wasm_global_t),
|
|
Memory(wasm_memory_t),
|
|
Table(wasm_table_t),
|
|
}
|
|
|
|
declare_vec!(wasm_extern_vec_t, *mut wasm_extern_t);
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_byte_vec_delete(v: *mut wasm_byte_vec_t) {
|
|
(*v).uninitialize();
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_byte_vec_new_uninitialized(out: *mut wasm_byte_vec_t, size: usize) {
|
|
(*out).set_uninitialized(size);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_engine_delete(engine: *mut wasm_engine_t) {
|
|
let _ = Box::from_raw(engine);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t {
|
|
let engine = Box::new(wasm_engine_t {
|
|
engine: HostRef::new(Engine::default()),
|
|
});
|
|
Box::into_raw(engine)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t {
|
|
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
|
(*e).cache = wasm_extern_t_type_cache::Func(wasm_func_t {
|
|
func: (*e).ext.func().unwrap().clone(),
|
|
ext: None,
|
|
});
|
|
}
|
|
|
|
match &mut (*e).cache {
|
|
wasm_extern_t_type_cache::Func(f) => f,
|
|
_ => panic!("wasm_extern_as_func"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_extern_vec_delete(v: *mut wasm_extern_vec_t) {
|
|
(*v).uninitialize();
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_func_as_extern(f: *mut wasm_func_t) -> *mut wasm_extern_t {
|
|
if (*f).ext.is_none() {
|
|
(*f).ext = Some(Box::new(wasm_extern_t {
|
|
ext: Extern::Func((*f).func.clone()),
|
|
cache: wasm_extern_t_type_cache::Empty,
|
|
}));
|
|
}
|
|
|
|
match &mut (*f).ext {
|
|
Some(e) => e.as_mut(),
|
|
_ => panic!("wasm_func_as_extern"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_func_call(
|
|
func: *const wasm_func_t,
|
|
args: *const wasm_val_t,
|
|
results: *mut wasm_val_t,
|
|
) -> *mut wasm_trap_t {
|
|
let func = (*func).func.borrow();
|
|
let mut params = Vec::with_capacity(func.param_arity());
|
|
for i in 0..func.param_arity() {
|
|
let val = &(*args.offset(i as isize));
|
|
params.push(val.val());
|
|
}
|
|
match func.call(¶ms) {
|
|
Ok(out) => {
|
|
for i in 0..func.result_arity() {
|
|
let val = &mut (*results.offset(i as isize));
|
|
*val = wasm_val_t::from_val(&out[i]);
|
|
}
|
|
ptr::null_mut()
|
|
}
|
|
Err(trap) => {
|
|
let trap = Box::new(wasm_trap_t { trap });
|
|
Box::into_raw(trap)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl wasm_val_t {
|
|
fn default() -> wasm_val_t {
|
|
wasm_val_t {
|
|
kind: 0,
|
|
of: wasm_val_t__bindgen_ty_1 { i32: 0 },
|
|
}
|
|
}
|
|
|
|
fn set(&mut self, val: Val) {
|
|
match val {
|
|
Val::I32(i) => {
|
|
self.kind = from_valtype(&ValType::I32);
|
|
self.of = wasm_val_t__bindgen_ty_1 { i32: i };
|
|
}
|
|
Val::I64(i) => {
|
|
self.kind = from_valtype(&ValType::I64);
|
|
self.of = wasm_val_t__bindgen_ty_1 { i64: i };
|
|
}
|
|
Val::F32(f) => {
|
|
self.kind = from_valtype(&ValType::F32);
|
|
self.of = wasm_val_t__bindgen_ty_1 { u32: f };
|
|
}
|
|
Val::F64(f) => {
|
|
self.kind = from_valtype(&ValType::F64);
|
|
self.of = wasm_val_t__bindgen_ty_1 { u64: f };
|
|
}
|
|
_ => unimplemented!("wasm_val_t::from_val {:?}", val),
|
|
}
|
|
}
|
|
|
|
fn from_val(val: &Val) -> wasm_val_t {
|
|
match val {
|
|
Val::I32(i) => wasm_val_t {
|
|
kind: from_valtype(&ValType::I32),
|
|
of: wasm_val_t__bindgen_ty_1 { i32: *i },
|
|
},
|
|
Val::I64(i) => wasm_val_t {
|
|
kind: from_valtype(&ValType::I64),
|
|
of: wasm_val_t__bindgen_ty_1 { i64: *i },
|
|
},
|
|
Val::F32(f) => wasm_val_t {
|
|
kind: from_valtype(&ValType::F32),
|
|
of: wasm_val_t__bindgen_ty_1 { u32: *f },
|
|
},
|
|
Val::F64(f) => wasm_val_t {
|
|
kind: from_valtype(&ValType::F64),
|
|
of: wasm_val_t__bindgen_ty_1 { u64: *f },
|
|
},
|
|
_ => unimplemented!("wasm_val_t::from_val {:?}", val),
|
|
}
|
|
}
|
|
|
|
fn val(&self) -> Val {
|
|
match into_valtype(self.kind) {
|
|
ValType::I32 => Val::from(unsafe { self.of.i32 }),
|
|
ValType::I64 => Val::from(unsafe { self.of.i64 }),
|
|
ValType::F32 => Val::from(unsafe { self.of.f32 }),
|
|
ValType::F64 => Val::from(unsafe { self.of.f64 }),
|
|
_ => unimplemented!("wasm_val_t::val {:?}", self.kind),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Callable for wasm_func_callback_t {
|
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
|
let params = params
|
|
.iter()
|
|
.map(|p| wasm_val_t::from_val(p))
|
|
.collect::<Vec<_>>();
|
|
let mut out_results = vec![wasm_val_t::default(); results.len()];
|
|
let func = self.expect("wasm_func_callback_t fn");
|
|
let out = unsafe { func(params.as_ptr(), out_results.as_mut_ptr()) };
|
|
if out != ptr::null_mut() {
|
|
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
|
|
return Err((*trap).into());
|
|
}
|
|
for i in 0..results.len() {
|
|
results[i] = out_results[i].val();
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Into<HostRef<Trap>> for wasm_trap_t {
|
|
fn into(self) -> HostRef<Trap> {
|
|
self.trap
|
|
}
|
|
}
|
|
|
|
struct CallbackWithEnv {
|
|
callback: wasm_func_callback_with_env_t,
|
|
env: *mut ::core::ffi::c_void,
|
|
finalizer: ::core::option::Option<unsafe extern "C" fn(env: *mut ::core::ffi::c_void)>,
|
|
}
|
|
|
|
impl Callable for CallbackWithEnv {
|
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
|
let params = params
|
|
.iter()
|
|
.map(|p| wasm_val_t::from_val(p))
|
|
.collect::<Vec<_>>();
|
|
let mut out_results = vec![wasm_val_t::default(); results.len()];
|
|
let func = self.callback.expect("wasm_func_callback_with_env_t fn");
|
|
let out = unsafe { func(self.env, params.as_ptr(), out_results.as_mut_ptr()) };
|
|
if out != ptr::null_mut() {
|
|
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
|
|
return Err((*trap).into());
|
|
}
|
|
for i in 0..results.len() {
|
|
results[i] = out_results[i].val();
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Drop for CallbackWithEnv {
|
|
fn drop(&mut self) {
|
|
if let Some(finalizer) = self.finalizer {
|
|
unsafe {
|
|
finalizer(self.env);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_func_new(
|
|
store: *mut wasm_store_t,
|
|
ty: *const wasm_functype_t,
|
|
callback: wasm_func_callback_t,
|
|
) -> *mut wasm_func_t {
|
|
let store = &(*store).store;
|
|
let ty = (*ty).functype.clone();
|
|
let callback = Rc::new(callback);
|
|
let func = Box::new(wasm_func_t {
|
|
func: HostRef::new(Func::new(store, ty, callback)),
|
|
ext: None,
|
|
});
|
|
Box::into_raw(func)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_func_delete(f: *mut wasm_func_t) {
|
|
let _ = Box::from_raw(f);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_functype_new(
|
|
params: *mut wasm_valtype_vec_t,
|
|
results: *mut wasm_valtype_vec_t,
|
|
) -> *mut wasm_functype_t {
|
|
let params = Vec::from_raw_parts((*params).data, (*params).size, (*params).size)
|
|
.into_iter()
|
|
.map(|vt| (*vt).ty.clone())
|
|
.collect::<Vec<_>>();
|
|
let results = Vec::from_raw_parts((*results).data, (*results).size, (*results).size)
|
|
.into_iter()
|
|
.map(|vt| (*vt).ty.clone())
|
|
.collect::<Vec<_>>();
|
|
let functype = FuncType::new(params.into_boxed_slice(), results.into_boxed_slice());
|
|
let functype = Box::new(wasm_functype_t {
|
|
functype,
|
|
params_cache: None, // TODO get from args?
|
|
returns_cache: None, // TODO get from args?
|
|
});
|
|
Box::into_raw(functype)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_functype_delete(ft: *mut wasm_functype_t) {
|
|
let _ = Box::from_raw(ft);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_instance_delete(instance: *mut wasm_instance_t) {
|
|
let _ = Box::from_raw(instance);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_instance_new(
|
|
store: *mut wasm_store_t,
|
|
module: *const wasm_module_t,
|
|
imports: *const *const wasm_extern_t,
|
|
result: *mut *mut wasm_trap_t,
|
|
) -> *mut wasm_instance_t {
|
|
let store = &(*store).store;
|
|
let mut externs: Vec<Extern> = Vec::with_capacity((*module).imports.len());
|
|
for i in 0..(*module).imports.len() {
|
|
let import = *imports.offset(i as isize);
|
|
externs.push((*import).ext.clone());
|
|
}
|
|
let module = &(*module).module;
|
|
match Instance::new(store, module, &externs) {
|
|
Ok(instance) => {
|
|
let instance = Box::new(wasm_instance_t {
|
|
instance: HostRef::new(instance),
|
|
});
|
|
if !result.is_null() {
|
|
(*result) = ptr::null_mut();
|
|
}
|
|
Box::into_raw(instance)
|
|
}
|
|
Err(_) => {
|
|
if !result.is_null() {
|
|
// TODO Unwrap trap from error
|
|
let trap = Box::new(wasm_trap_t {
|
|
trap: HostRef::new(Trap::new("trap during instantiation".to_string())),
|
|
});
|
|
(*result) = Box::into_raw(trap);
|
|
}
|
|
ptr::null_mut()
|
|
}
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_instance_exports(
|
|
instance: *const wasm_instance_t,
|
|
out: *mut wasm_extern_vec_t,
|
|
) {
|
|
let instance = &(*instance).instance.borrow();
|
|
let exports = instance.exports();
|
|
let mut buffer = Vec::with_capacity(exports.len());
|
|
for e in exports.iter() {
|
|
let ext = Box::new(wasm_extern_t {
|
|
ext: e.clone(),
|
|
cache: wasm_extern_t_type_cache::Empty,
|
|
});
|
|
buffer.push(Box::into_raw(ext));
|
|
}
|
|
(*out).set_buffer(buffer);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_module_delete(module: *mut wasm_module_t) {
|
|
let _ = Box::from_raw(module);
|
|
}
|
|
|
|
impl wasm_name_t {
|
|
fn from_name(name: &Name) -> wasm_name_t {
|
|
let s = name.to_string();
|
|
let mut buffer = Vec::new();
|
|
buffer.extend_from_slice(s.as_bytes());
|
|
buffer.into()
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_module_new(
|
|
store: *mut wasm_store_t,
|
|
binary: *const wasm_byte_vec_t,
|
|
) -> *mut wasm_module_t {
|
|
let binary = (*binary).as_slice();
|
|
let store = &(*store).store;
|
|
let module = Module::new(store, binary).expect("module");
|
|
let imports = module
|
|
.imports()
|
|
.iter()
|
|
.map(|i| wasm_importtype_t {
|
|
ty: i.clone(),
|
|
module_cache: None,
|
|
name_cache: None,
|
|
})
|
|
.collect::<Vec<_>>();
|
|
let exports = module
|
|
.exports()
|
|
.iter()
|
|
.map(|e| wasm_exporttype_t {
|
|
ty: e.clone(),
|
|
name_cache: None,
|
|
type_cache: None,
|
|
})
|
|
.collect::<Vec<_>>();
|
|
let module = Box::new(wasm_module_t {
|
|
module: HostRef::new(module),
|
|
imports,
|
|
exports,
|
|
});
|
|
Box::into_raw(module)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_store_delete(store: *mut wasm_store_t) {
|
|
let _ = Box::from_raw(store);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_store_new(engine: *mut wasm_engine_t) -> *mut wasm_store_t {
|
|
let engine = &(*engine).engine;
|
|
let store = Box::new(wasm_store_t {
|
|
store: HostRef::new(Store::new(&engine)),
|
|
});
|
|
Box::into_raw(store)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_valtype_vec_new_empty(out: *mut wasm_valtype_vec_t) {
|
|
(*out).set_uninitialized(0);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_valtype_vec_new(
|
|
out: *mut wasm_valtype_vec_t,
|
|
size: usize,
|
|
data: *const *mut wasm_valtype_t,
|
|
) {
|
|
let slice = slice::from_raw_parts(data, size);
|
|
(*out).set_from_slice(slice);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_valtype_vec_new_uninitialized(
|
|
out: *mut wasm_valtype_vec_t,
|
|
size: usize,
|
|
) {
|
|
(*out).set_uninitialized(size);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_func_new_with_env(
|
|
store: *mut wasm_store_t,
|
|
ty: *const wasm_functype_t,
|
|
callback: wasm_func_callback_with_env_t,
|
|
env: *mut ::core::ffi::c_void,
|
|
finalizer: ::core::option::Option<unsafe extern "C" fn(arg1: *mut ::core::ffi::c_void)>,
|
|
) -> *mut wasm_func_t {
|
|
let store = &(*store).store;
|
|
let ty = (*ty).functype.clone();
|
|
let callback = Rc::new(CallbackWithEnv {
|
|
callback,
|
|
env,
|
|
finalizer,
|
|
});
|
|
let func = Box::new(wasm_func_t {
|
|
func: HostRef::new(Func::new(store, ty, callback)),
|
|
ext: None,
|
|
});
|
|
Box::into_raw(func)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_val_copy(out: *mut wasm_val_t, source: *const wasm_val_t) {
|
|
*out = match into_valtype((*source).kind) {
|
|
ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 => (*source).clone(),
|
|
_ => unimplemented!("wasm_val_copy arg"),
|
|
};
|
|
}
|
|
|
|
fn into_valtype(kind: wasm_valkind_t) -> ValType {
|
|
match kind {
|
|
0 => ValType::I32,
|
|
1 => ValType::I64,
|
|
2 => ValType::F32,
|
|
3 => ValType::F64,
|
|
128 => ValType::AnyRef,
|
|
129 => ValType::FuncRef,
|
|
_ => panic!("unexpected kind: {}", kind),
|
|
}
|
|
}
|
|
|
|
fn from_valtype(ty: &ValType) -> wasm_valkind_t {
|
|
match ty {
|
|
ValType::I32 => 0,
|
|
ValType::I64 => 1,
|
|
ValType::F32 => 2,
|
|
ValType::F64 => 3,
|
|
ValType::AnyRef => 128,
|
|
ValType::FuncRef => 129,
|
|
_ => panic!("wasm_valkind_t has no known conversion for {:?}", ty),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> *mut wasm_valtype_t {
|
|
let ty = Box::new(wasm_valtype_t {
|
|
ty: into_valtype(kind),
|
|
});
|
|
Box::into_raw(ty)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_valtype_delete(vt: *mut wasm_valtype_t) {
|
|
drop(Box::from_raw(vt));
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_byte_vec_new(
|
|
out: *mut wasm_byte_vec_t,
|
|
size: usize,
|
|
data: *const wasm_byte_t,
|
|
) {
|
|
let slice = slice::from_raw_parts(data, size);
|
|
(*out).set_from_slice(slice);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_frame_delete(_arg1: *mut wasm_frame_t) {
|
|
unimplemented!("wasm_frame_delete")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_frame_func_index(_arg1: *const wasm_frame_t) -> u32 {
|
|
unimplemented!("wasm_frame_func_index")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_frame_func_offset(_arg1: *const wasm_frame_t) -> usize {
|
|
unimplemented!("wasm_frame_func_offset")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_frame_instance(_arg1: *const wasm_frame_t) -> *mut wasm_instance_t {
|
|
unimplemented!("wasm_frame_instance")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_frame_module_offset(_arg1: *const wasm_frame_t) -> usize {
|
|
unimplemented!("wasm_frame_module_offset")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_frame_vec_delete(frames: *mut wasm_frame_vec_t) {
|
|
(*frames).uninitialize();
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_trap_delete(trap: *mut wasm_trap_t) {
|
|
let _ = Box::from_raw(trap);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_trap_new(
|
|
_store: *mut wasm_store_t,
|
|
message: *const wasm_message_t,
|
|
) -> *mut wasm_trap_t {
|
|
let message = (*message).as_slice();
|
|
if message[message.len() - 1] != 0 {
|
|
panic!("wasm_trap_new message stringz expected");
|
|
}
|
|
let message = String::from_utf8_lossy(message).to_string();
|
|
let trap = Box::new(wasm_trap_t {
|
|
trap: HostRef::new(Trap::new(message)),
|
|
});
|
|
Box::into_raw(trap)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_trap_message(trap: *const wasm_trap_t, out: *mut wasm_message_t) {
|
|
let mut buffer = Vec::new();
|
|
buffer.extend_from_slice((*trap).trap.borrow().message().as_bytes());
|
|
buffer.reserve_exact(1);
|
|
buffer.push(0);
|
|
(*out).set_buffer(buffer);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_trap_origin(_trap: *const wasm_trap_t) -> *mut wasm_frame_t {
|
|
ptr::null_mut()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_trap_trace(_trap: *const wasm_trap_t, out: *mut wasm_frame_vec_t) {
|
|
(*out).set_uninitialized(0);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_importtype_module(
|
|
it: *const wasm_importtype_t,
|
|
) -> *const wasm_name_t {
|
|
if (*it).module_cache.is_none() {
|
|
let it = (it as *mut wasm_importtype_t).as_mut().unwrap();
|
|
it.module_cache = Some(wasm_name_t::from_name(&it.ty.module()));
|
|
}
|
|
(*it).module_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_importtype_name(it: *const wasm_importtype_t) -> *const wasm_name_t {
|
|
if (*it).name_cache.is_none() {
|
|
let it = (it as *mut wasm_importtype_t).as_mut().unwrap();
|
|
it.name_cache = Some(wasm_name_t::from_name(&it.ty.name()));
|
|
}
|
|
(*it).name_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_importtype_type(
|
|
it: *const wasm_importtype_t,
|
|
) -> *const wasm_externtype_t {
|
|
let ty = Box::new(wasm_externtype_t {
|
|
ty: (*it).ty.r#type().clone(),
|
|
cache: wasm_externtype_t_type_cache::Empty,
|
|
});
|
|
Box::into_raw(ty)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_importtype_vec_delete(vec: *mut wasm_importtype_vec_t) {
|
|
(*vec).uninitialize();
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_exporttype_name(et: *const wasm_exporttype_t) -> *const wasm_name_t {
|
|
if (*et).name_cache.is_none() {
|
|
let et = (et as *mut wasm_exporttype_t).as_mut().unwrap();
|
|
et.name_cache = Some(wasm_name_t::from_name(&et.ty.name()));
|
|
}
|
|
(*et).name_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_exporttype_type(
|
|
et: *const wasm_exporttype_t,
|
|
) -> *const wasm_externtype_t {
|
|
if (*et).type_cache.is_none() {
|
|
let et = (et as *mut wasm_exporttype_t).as_mut().unwrap();
|
|
et.type_cache = Some(wasm_externtype_t {
|
|
ty: (*et).ty.r#type().clone(),
|
|
cache: wasm_externtype_t_type_cache::Empty,
|
|
});
|
|
}
|
|
(*et).type_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_exporttype_vec_delete(et: *mut wasm_exporttype_vec_t) {
|
|
(*et).uninitialize();
|
|
}
|
|
|
|
fn from_externtype(ty: &ExternType) -> wasm_externkind_t {
|
|
match ty {
|
|
ExternType::ExternFunc(_) => 0,
|
|
ExternType::ExternGlobal(_) => 1,
|
|
ExternType::ExternTable(_) => 2,
|
|
ExternType::ExternMemory(_) => 3,
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_extern_kind(e: *const wasm_extern_t) -> wasm_externkind_t {
|
|
from_externtype(&(*e).ext.r#type())
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_extern_type(e: *const wasm_extern_t) -> *mut wasm_externtype_t {
|
|
let et = Box::new(wasm_externtype_t {
|
|
ty: (*e).ext.r#type(),
|
|
cache: wasm_externtype_t_type_cache::Empty,
|
|
});
|
|
Box::into_raw(et)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_externtype_as_functype_const(
|
|
et: *const wasm_externtype_t,
|
|
) -> *const wasm_functype_t {
|
|
if let wasm_externtype_t_type_cache::Empty = (*et).cache {
|
|
let functype = (*et).ty.func().clone();
|
|
let f = wasm_functype_t {
|
|
functype,
|
|
params_cache: None,
|
|
returns_cache: None,
|
|
};
|
|
let et = (et as *mut wasm_externtype_t).as_mut().unwrap();
|
|
et.cache = wasm_externtype_t_type_cache::Func(f);
|
|
}
|
|
match &(*et).cache {
|
|
wasm_externtype_t_type_cache::Func(f) => f,
|
|
_ => panic!("wasm_externtype_as_functype_const"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_externtype_as_globaltype_const(
|
|
et: *const wasm_externtype_t,
|
|
) -> *const wasm_globaltype_t {
|
|
if let wasm_externtype_t_type_cache::Empty = (*et).cache {
|
|
let globaltype = (*et).ty.global().clone();
|
|
let g = wasm_globaltype_t {
|
|
globaltype,
|
|
content_cache: None,
|
|
};
|
|
let et = (et as *mut wasm_externtype_t).as_mut().unwrap();
|
|
et.cache = wasm_externtype_t_type_cache::Global(g);
|
|
}
|
|
match &(*et).cache {
|
|
wasm_externtype_t_type_cache::Global(g) => g,
|
|
_ => panic!("wasm_externtype_as_globaltype_const"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_externtype_as_tabletype_const(
|
|
et: *const wasm_externtype_t,
|
|
) -> *const wasm_tabletype_t {
|
|
if let wasm_externtype_t_type_cache::Empty = (*et).cache {
|
|
let tabletype = (*et).ty.table().clone();
|
|
let t = wasm_tabletype_t {
|
|
tabletype,
|
|
element_cache: None,
|
|
limits_cache: None,
|
|
};
|
|
let et = (et as *mut wasm_externtype_t).as_mut().unwrap();
|
|
et.cache = wasm_externtype_t_type_cache::Table(t);
|
|
}
|
|
match &(*et).cache {
|
|
wasm_externtype_t_type_cache::Table(t) => t,
|
|
_ => panic!("wasm_externtype_as_tabletype_const"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_externtype_as_memorytype_const(
|
|
et: *const wasm_externtype_t,
|
|
) -> *const wasm_memorytype_t {
|
|
if let wasm_externtype_t_type_cache::Empty = (*et).cache {
|
|
let memorytype = (*et).ty.memory().clone();
|
|
let m = wasm_memorytype_t {
|
|
memorytype,
|
|
limits_cache: None,
|
|
};
|
|
let et = (et as *mut wasm_externtype_t).as_mut().unwrap();
|
|
et.cache = wasm_externtype_t_type_cache::Memory(m);
|
|
}
|
|
match &(*et).cache {
|
|
wasm_externtype_t_type_cache::Memory(m) => m,
|
|
_ => panic!("wasm_externtype_as_memorytype_const"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_externtype_delete(et: *mut wasm_externtype_t) {
|
|
let _ = Box::from_raw(et);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_externtype_kind(et: *const wasm_externtype_t) -> wasm_externkind_t {
|
|
from_externtype(&(*et).ty)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_func_param_arity(f: *const wasm_func_t) -> usize {
|
|
(*f).func.borrow().param_arity()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_func_result_arity(f: *const wasm_func_t) -> usize {
|
|
(*f).func.borrow().result_arity()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_functype_params(
|
|
ft: *const wasm_functype_t,
|
|
) -> *const wasm_valtype_vec_t {
|
|
if (*ft).params_cache.is_none() {
|
|
let ft = (ft as *mut wasm_functype_t).as_mut().unwrap();
|
|
let buffer = ft
|
|
.functype
|
|
.params()
|
|
.iter()
|
|
.map(|p| {
|
|
let ty = Box::new(wasm_valtype_t { ty: p.clone() });
|
|
Box::into_raw(ty)
|
|
})
|
|
.collect::<Vec<_>>();
|
|
ft.params_cache = Some(buffer.into());
|
|
}
|
|
(*ft).params_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_functype_results(
|
|
ft: *const wasm_functype_t,
|
|
) -> *const wasm_valtype_vec_t {
|
|
if (*ft).returns_cache.is_none() {
|
|
let ft = (ft as *mut wasm_functype_t).as_mut().unwrap();
|
|
let buffer = ft
|
|
.functype
|
|
.results()
|
|
.iter()
|
|
.map(|p| {
|
|
let ty = Box::new(wasm_valtype_t { ty: p.clone() });
|
|
Box::into_raw(ty)
|
|
})
|
|
.collect::<Vec<_>>();
|
|
ft.returns_cache = Some(buffer.into());
|
|
}
|
|
(*ft).returns_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_globaltype_content(
|
|
gt: *const wasm_globaltype_t,
|
|
) -> *const wasm_valtype_t {
|
|
if (*gt).content_cache.is_none() {
|
|
let gt = (gt as *mut wasm_globaltype_t).as_mut().unwrap();
|
|
gt.content_cache = Some(wasm_valtype_t {
|
|
ty: (*gt).globaltype.content().clone(),
|
|
});
|
|
}
|
|
(*gt).content_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_globaltype_mutability(
|
|
gt: *const wasm_globaltype_t,
|
|
) -> wasm_mutability_t {
|
|
use super::Mutability::*;
|
|
match (*gt).globaltype.mutability() {
|
|
Const => 0,
|
|
Var => 1,
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memorytype_limits(
|
|
mt: *const wasm_memorytype_t,
|
|
) -> *const wasm_limits_t {
|
|
if (*mt).limits_cache.is_none() {
|
|
let mt = (mt as *mut wasm_memorytype_t).as_mut().unwrap();
|
|
let limits = (*mt).memorytype.limits();
|
|
mt.limits_cache = Some(wasm_limits_t {
|
|
min: limits.min(),
|
|
max: limits.max(),
|
|
});
|
|
}
|
|
(*mt).limits_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_module_exports(
|
|
module: *const wasm_module_t,
|
|
out: *mut wasm_exporttype_vec_t,
|
|
) {
|
|
let buffer = (*module)
|
|
.exports
|
|
.iter()
|
|
.map(|et| {
|
|
let et = Box::new(et.clone());
|
|
Box::into_raw(et)
|
|
})
|
|
.collect::<Vec<_>>();
|
|
(*out).set_buffer(buffer);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_module_imports(
|
|
module: *const wasm_module_t,
|
|
out: *mut wasm_importtype_vec_t,
|
|
) {
|
|
let buffer = (*module)
|
|
.imports
|
|
.iter()
|
|
.map(|it| {
|
|
let it = Box::new(it.clone());
|
|
Box::into_raw(it)
|
|
})
|
|
.collect::<Vec<_>>();
|
|
(*out).set_buffer(buffer);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_tabletype_element(
|
|
tt: *const wasm_tabletype_t,
|
|
) -> *const wasm_valtype_t {
|
|
if (*tt).element_cache.is_none() {
|
|
let tt = (tt as *mut wasm_tabletype_t).as_mut().unwrap();
|
|
tt.element_cache = Some(wasm_valtype_t {
|
|
ty: (*tt).tabletype.element().clone(),
|
|
});
|
|
}
|
|
(*tt).element_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_tabletype_limits(
|
|
tt: *const wasm_tabletype_t,
|
|
) -> *const wasm_limits_t {
|
|
if (*tt).limits_cache.is_none() {
|
|
let tt = (tt as *mut wasm_tabletype_t).as_mut().unwrap();
|
|
let limits = (*tt).tabletype.limits();
|
|
tt.limits_cache = Some(wasm_limits_t {
|
|
min: limits.min(),
|
|
max: limits.max(),
|
|
});
|
|
}
|
|
(*tt).limits_cache.as_ref().unwrap()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_valtype_kind(vt: *const wasm_valtype_t) -> wasm_valkind_t {
|
|
from_valtype(&(*vt).ty)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_extern_as_global(e: *mut wasm_extern_t) -> *mut wasm_global_t {
|
|
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
|
(*e).cache = wasm_extern_t_type_cache::Global(wasm_global_t {
|
|
global: (*e).ext.global().unwrap().clone(),
|
|
ext: None,
|
|
});
|
|
}
|
|
|
|
match &mut (*e).cache {
|
|
wasm_extern_t_type_cache::Global(g) => g,
|
|
_ => panic!("wasm_extern_as_global"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t {
|
|
if (*g).ext.is_none() {
|
|
(*g).ext = Some(Box::new(wasm_extern_t {
|
|
ext: Extern::Global((*g).global.clone()),
|
|
cache: wasm_extern_t_type_cache::Empty,
|
|
}));
|
|
}
|
|
|
|
match &mut (*g).ext {
|
|
Some(e) => e.as_mut(),
|
|
_ => panic!("wasm_global_as_extern"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_global_delete(g: *mut wasm_global_t) {
|
|
let _ = Box::from_raw(g);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_global_copy(g: *const wasm_global_t) -> *mut wasm_global_t {
|
|
Box::into_raw(Box::new((*g).clone()))
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_global_same(
|
|
g1: *const wasm_global_t,
|
|
g2: *const wasm_global_t,
|
|
) -> bool {
|
|
(*g1).global.ptr_eq(&(*g2).global)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_global_new(
|
|
store: *mut wasm_store_t,
|
|
gt: *const wasm_globaltype_t,
|
|
val: *const wasm_val_t,
|
|
) -> *mut wasm_global_t {
|
|
let global = HostRef::new(Global::new(
|
|
&(*store).store,
|
|
(*gt).globaltype.clone(),
|
|
(*val).val(),
|
|
));
|
|
let g = Box::new(wasm_global_t { global, ext: None });
|
|
Box::into_raw(g)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_global_get(g: *const wasm_global_t, out: *mut wasm_val_t) {
|
|
(*out).set((*g).global.borrow_mut().get());
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_global_set(g: *mut wasm_global_t, val: *const wasm_val_t) {
|
|
(*g).global.borrow_mut().set((*val).val())
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_globaltype_delete(gt: *mut wasm_globaltype_t) {
|
|
let _ = Box::from_raw(gt);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_globaltype_new(
|
|
ty: *mut wasm_valtype_t,
|
|
mutability: wasm_mutability_t,
|
|
) -> *mut wasm_globaltype_t {
|
|
use super::Mutability::*;
|
|
let ty = Box::from_raw(ty);
|
|
let mutability = match mutability {
|
|
0 => Const,
|
|
1 => Var,
|
|
_ => panic!("mutability out-of-range"),
|
|
};
|
|
let globaltype = GlobalType::new(ty.ty.clone(), mutability);
|
|
let gt = Box::new(wasm_globaltype_t {
|
|
globaltype,
|
|
content_cache: Some(*ty),
|
|
});
|
|
Box::into_raw(gt)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_extern_as_memory(e: *mut wasm_extern_t) -> *mut wasm_memory_t {
|
|
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
|
(*e).cache = wasm_extern_t_type_cache::Memory(wasm_memory_t {
|
|
memory: (*e).ext.memory().unwrap().clone(),
|
|
ext: None,
|
|
});
|
|
}
|
|
|
|
match &mut (*e).cache {
|
|
wasm_extern_t_type_cache::Memory(m) => m,
|
|
_ => panic!("wasm_extern_as_memory"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memory_as_extern(m: *mut wasm_memory_t) -> *mut wasm_extern_t {
|
|
if (*m).ext.is_none() {
|
|
(*m).ext = Some(Box::new(wasm_extern_t {
|
|
ext: Extern::Memory((*m).memory.clone()),
|
|
cache: wasm_extern_t_type_cache::Empty,
|
|
}));
|
|
}
|
|
|
|
match &mut (*m).ext {
|
|
Some(e) => e.as_mut(),
|
|
_ => panic!("wasm_global_as_extern"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memory_delete(m: *mut wasm_memory_t) {
|
|
let _ = Box::from_raw(m);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memory_copy(m: *const wasm_memory_t) -> *mut wasm_memory_t {
|
|
Box::into_raw(Box::new((*m).clone()))
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memory_same(
|
|
m1: *const wasm_memory_t,
|
|
m2: *const wasm_memory_t,
|
|
) -> bool {
|
|
(*m1).memory.ptr_eq(&(*m2).memory)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memory_data(m: *mut wasm_memory_t) -> *mut u8 {
|
|
(*m).memory.borrow().data_ptr()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memory_data_size(m: *const wasm_memory_t) -> usize {
|
|
(*m).memory.borrow().data_size()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memory_size(m: *const wasm_memory_t) -> wasm_memory_pages_t {
|
|
(*m).memory.borrow().size()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memory_grow(
|
|
m: *mut wasm_memory_t,
|
|
delta: wasm_memory_pages_t,
|
|
) -> bool {
|
|
(*m).memory.borrow_mut().grow(delta)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memory_new(
|
|
store: *mut wasm_store_t,
|
|
mt: *const wasm_memorytype_t,
|
|
) -> *mut wasm_memory_t {
|
|
let memory = HostRef::new(Memory::new(&(*store).store, (*mt).memorytype.clone()));
|
|
let m = Box::new(wasm_memory_t { memory, ext: None });
|
|
Box::into_raw(m)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memorytype_delete(mt: *mut wasm_memorytype_t) {
|
|
let _ = Box::from_raw(mt);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_memorytype_new(
|
|
limits: *const wasm_limits_t,
|
|
) -> *mut wasm_memorytype_t {
|
|
let limits = Limits::new((*limits).min, (*limits).max);
|
|
let mt = Box::new(wasm_memorytype_t {
|
|
memorytype: MemoryType::new(limits),
|
|
limits_cache: None,
|
|
});
|
|
Box::into_raw(mt)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_extern_as_table(e: *mut wasm_extern_t) -> *mut wasm_table_t {
|
|
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
|
(*e).cache = wasm_extern_t_type_cache::Table(wasm_table_t {
|
|
table: (*e).ext.table().unwrap().clone(),
|
|
ext: None,
|
|
});
|
|
}
|
|
|
|
match &mut (*e).cache {
|
|
wasm_extern_t_type_cache::Table(t) => t,
|
|
_ => panic!("wasm_extern_as_table"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_table_as_extern(t: *mut wasm_table_t) -> *mut wasm_extern_t {
|
|
if (*t).ext.is_none() {
|
|
(*t).ext = Some(Box::new(wasm_extern_t {
|
|
ext: Extern::Table((*t).table.clone()),
|
|
cache: wasm_extern_t_type_cache::Empty,
|
|
}));
|
|
}
|
|
|
|
match &mut (*t).ext {
|
|
Some(e) => e.as_mut(),
|
|
_ => panic!("wasm_table_as_extern"),
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_func_as_ref(f: *mut wasm_func_t) -> *mut wasm_ref_t {
|
|
let r = (*f).func.anyref();
|
|
let f = Box::new(wasm_ref_t { r });
|
|
Box::into_raw(f)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_ref_delete(r: *mut wasm_ref_t) {
|
|
if !r.is_null() {
|
|
let _ = Box::from_raw(r);
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_table_delete(t: *mut wasm_table_t) {
|
|
let _ = Box::from_raw(t);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_table_copy(t: *const wasm_table_t) -> *mut wasm_table_t {
|
|
Box::into_raw(Box::new((*t).clone()))
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_table_new(
|
|
store: *mut wasm_store_t,
|
|
tt: *const wasm_tabletype_t,
|
|
init: *mut wasm_ref_t,
|
|
) -> *mut wasm_table_t {
|
|
let init: Val = if !init.is_null() {
|
|
Box::from_raw(init).r.into()
|
|
} else {
|
|
Val::AnyRef(AnyRef::Null)
|
|
};
|
|
let t = Box::new(wasm_table_t {
|
|
table: HostRef::new(Table::new(&(*store).store, (*tt).tabletype.clone(), init)),
|
|
ext: None,
|
|
});
|
|
Box::into_raw(t)
|
|
}
|
|
|
|
unsafe fn into_funcref(val: Val) -> *mut wasm_ref_t {
|
|
if let Val::AnyRef(AnyRef::Null) = val {
|
|
return ptr::null_mut();
|
|
}
|
|
let r = Box::new(wasm_ref_t { r: val.into() });
|
|
Box::into_raw(r)
|
|
}
|
|
|
|
unsafe fn from_funcref(r: *mut wasm_ref_t) -> Val {
|
|
if !r.is_null() {
|
|
Box::from_raw(r).r.into()
|
|
} else {
|
|
Val::AnyRef(AnyRef::Null)
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_table_get(
|
|
t: *const wasm_table_t,
|
|
index: wasm_table_size_t,
|
|
) -> *mut wasm_ref_t {
|
|
let val = (*t).table.borrow().get(index);
|
|
into_funcref(val)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_table_set(
|
|
t: *mut wasm_table_t,
|
|
index: wasm_table_size_t,
|
|
r: *mut wasm_ref_t,
|
|
) -> bool {
|
|
let val = from_funcref(r);
|
|
(*t).table.borrow().set(index, val)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_table_size(t: *const wasm_table_t) -> wasm_table_size_t {
|
|
(*t).table.borrow().size()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_table_grow(
|
|
t: *mut wasm_table_t,
|
|
delta: wasm_table_size_t,
|
|
init: *mut wasm_ref_t,
|
|
) -> bool {
|
|
let init = from_funcref(init);
|
|
(*t).table.borrow_mut().grow(delta, init)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_table_same(t1: *const wasm_table_t, t2: *const wasm_table_t) -> bool {
|
|
(*t1).table.ptr_eq(&(*t2).table)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_tabletype_delete(tt: *mut wasm_tabletype_t) {
|
|
let _ = Box::from_raw(tt);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_tabletype_new(
|
|
ty: *mut wasm_valtype_t,
|
|
limits: *const wasm_limits_t,
|
|
) -> *mut wasm_tabletype_t {
|
|
let ty = Box::from_raw(ty).ty;
|
|
let limits = Limits::new((*limits).min, (*limits).max);
|
|
let tt = Box::new(wasm_tabletype_t {
|
|
tabletype: TableType::new(ty, limits),
|
|
element_cache: None,
|
|
limits_cache: None,
|
|
});
|
|
Box::into_raw(tt)
|
|
}
|
|
|
|
struct HostInfoState {
|
|
info: *mut ::core::ffi::c_void,
|
|
finalizer: ::core::option::Option<unsafe extern "C" fn(arg1: *mut ::core::ffi::c_void)>,
|
|
}
|
|
|
|
impl HostInfo for HostInfoState {
|
|
fn finalize(&mut self) {
|
|
if let Some(f) = &self.finalizer {
|
|
unsafe {
|
|
f(self.info);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_instance_set_host_info_with_finalizer(
|
|
instance: *mut wasm_instance_t,
|
|
info: *mut ::core::ffi::c_void,
|
|
finalizer: ::core::option::Option<unsafe extern "C" fn(arg1: *mut ::core::ffi::c_void)>,
|
|
) {
|
|
let info = if info.is_null() && finalizer.is_none() {
|
|
None
|
|
} else {
|
|
let b: Box<dyn HostInfo> = Box::new(HostInfoState { info, finalizer });
|
|
Some(b)
|
|
};
|
|
(*instance).instance.anyref().set_host_info(info);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wasm_valtype_vec_copy(
|
|
out: *mut wasm_valtype_vec_t,
|
|
src: *mut wasm_valtype_vec_t,
|
|
) {
|
|
let slice = slice::from_raw_parts((*src).data, (*src).size);
|
|
(*out).set_from_slice(slice);
|
|
}
|