diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs new file mode 100644 index 000000000..d58336e62 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -0,0 +1,104 @@ +use super::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_store_t, wasm_trap_t}; +use crate::c_try; +use crate::ordered_resolver::OrderedResolver; +use std::mem; +use std::ptr::NonNull; +use std::sync::Arc; +use wasmer::{Extern, Instance}; + +#[repr(C)] +pub struct wasm_instance_t { + pub(crate) inner: Arc, +} + +struct CArrayIter { + cur_entry: *const *const T, +} + +impl CArrayIter { + fn new(array: *const *const T) -> Option { + if array.is_null() { + None + } else { + Some(CArrayIter { cur_entry: array }) + } + } +} + +impl Iterator for CArrayIter { + type Item = &'static T; + + fn next(&mut self) -> Option { + let next_entry_candidate = unsafe { *self.cur_entry }; + if next_entry_candidate.is_null() { + None + } else { + self.cur_entry = unsafe { self.cur_entry.add(1) }; + Some(unsafe { &*next_entry_candidate }) + } + } +} + +// reads from null-terminated array of `wasm_extern_t`s +unsafe fn argument_import_iter( + imports: *const *const wasm_extern_t, +) -> Box> { + CArrayIter::new(imports) + .map(|it| Box::new(it) as _) + .unwrap_or_else(|| Box::new(std::iter::empty()) as _) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_instance_new( + store: Option>, + module: &wasm_module_t, + imports: *const *const wasm_extern_t, + // own + _traps: *mut *mut wasm_trap_t, +) -> Option> { + let wasm_module = &module.inner; + let module_imports = wasm_module.imports(); + let module_import_count = module_imports.len(); + let imports = argument_import_iter(imports); + let resolver: OrderedResolver = imports + .map(|imp| &imp.inner) + .take(module_import_count) + .cloned() + .collect(); + + let instance = Arc::new(c_try!(Instance::new(wasm_module, &resolver))); + Some(Box::new(wasm_instance_t { inner: instance })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_instance_exports( + instance: &wasm_instance_t, + // TODO: review types on wasm_declare_vec, handle the optional pointer part properly + out: &mut wasm_extern_vec_t, +) { + let instance = &instance.inner; + let mut extern_vec = instance + .exports + .iter() + .map(|(name, r#extern)| { + let function = if let Extern::Function { .. } = r#extern { + instance.exports.get_function(&name).ok().cloned() + } else { + None + }; + Box::into_raw(Box::new(wasm_extern_t { + instance: Some(Arc::clone(instance)), + inner: r#extern.clone(), + })) + }) + .collect::>(); + extern_vec.shrink_to_fit(); + + out.size = extern_vec.len(); + out.data = extern_vec.as_mut_ptr(); + // TODO: double check that the destructor will work correctly here + mem::forget(extern_vec); +} diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 4a6a62aaa..a84d315d1 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -2,6 +2,7 @@ pub mod engine; pub mod externals; +pub mod instance; pub mod module; pub mod store; pub(crate) mod utils; @@ -12,7 +13,6 @@ pub mod wasi; // required due to really weird Rust resolution rules // https://github.com/rust-lang/rust/issues/57966 use crate::c_try; -use crate::ordered_resolver::OrderedResolver; use externals::function::wasm_func_t; use externals::global::wasm_global_t; use externals::memory::wasm_memory_t; @@ -33,103 +33,6 @@ use wasmer::{ #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; -#[repr(C)] -pub struct wasm_instance_t { - inner: Arc, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_instance_new( - store: Option>, - module: &wasm_module_t, - imports: *const *const wasm_extern_t, - // own - _traps: *mut *mut wasm_trap_t, -) -> Option> { - let wasm_module = &module.inner; - let module_imports = wasm_module.imports(); - let module_import_count = module_imports.len(); - let imports = argument_import_iter(imports); - let resolver: OrderedResolver = imports - .map(|imp| &imp.inner) - .take(module_import_count) - .cloned() - .collect(); - - let instance = Arc::new(c_try!(Instance::new(wasm_module, &resolver))); - Some(Box::new(wasm_instance_t { inner: instance })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>) {} - -struct CArrayIter { - cur_entry: *const *const T, -} - -impl CArrayIter { - fn new(array: *const *const T) -> Option { - if array.is_null() { - None - } else { - Some(CArrayIter { cur_entry: array }) - } - } -} - -impl Iterator for CArrayIter { - type Item = &'static T; - - fn next(&mut self) -> Option { - let next_entry_candidate = unsafe { *self.cur_entry }; - if next_entry_candidate.is_null() { - None - } else { - self.cur_entry = unsafe { self.cur_entry.add(1) }; - Some(unsafe { &*next_entry_candidate }) - } - } -} - -// reads from null-terminated array of `wasm_extern_t`s -unsafe fn argument_import_iter( - imports: *const *const wasm_extern_t, -) -> Box> { - CArrayIter::new(imports) - .map(|it| Box::new(it) as _) - .unwrap_or_else(|| Box::new(std::iter::empty()) as _) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_instance_exports( - instance: &wasm_instance_t, - // TODO: review types on wasm_declare_vec, handle the optional pointer part properly - out: &mut wasm_extern_vec_t, -) { - let instance = &instance.inner; - let mut extern_vec = instance - .exports - .iter() - .map(|(name, r#extern)| { - let function = if let Extern::Function { .. } = r#extern { - instance.exports.get_function(&name).ok().cloned() - } else { - None - }; - Box::into_raw(Box::new(wasm_extern_t { - instance: Some(Arc::clone(instance)), - inner: r#extern.clone(), - })) - }) - .collect::>(); - extern_vec.shrink_to_fit(); - - out.size = extern_vec.len(); - out.data = extern_vec.as_mut_ptr(); - // TODO: double check that the destructor will work correctly here - mem::forget(extern_vec); -} - #[no_mangle] pub unsafe extern "C" fn wasm_func_as_extern( func_ptr: Option>, diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 4a51240e7..ad18010b4 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -5,8 +5,8 @@ mod capture_files; use super::{ - externals::memory::wasm_memory_t, wasm_extern_t, wasm_func_t, wasm_instance_t, wasm_module_t, - wasm_store_t, + externals::memory::wasm_memory_t, instance::wasm_instance_t, wasm_extern_t, wasm_func_t, + wasm_module_t, wasm_store_t, }; // required due to really weird Rust resolution rules for macros // https://github.com/rust-lang/rust/issues/57966