Make caller responsible for allocation array for getting WASI imports

This commit is contained in:
Mark McCaskey
2020-08-12 17:08:58 -07:00
parent 2e36c8e63b
commit 892fb4efcf
4 changed files with 151 additions and 14 deletions

View File

@@ -17,9 +17,9 @@ use crate::c_try;
use crate::ordered_resolver::OrderedResolver;
use wasmer::{
Engine, ExportType, Extern, ExternType, Function, FunctionType, Global, GlobalType, Instance,
Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType, Val,
ValType,
Engine, ExportType, Extern, ExternType, Function, FunctionType, Global, GlobalType, ImportType,
Instance, Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType,
Val, ValType,
};
#[cfg(feature = "jit")]
use wasmer_engine_jit::JIT;
@@ -230,6 +230,25 @@ pub unsafe extern "C" fn wasm_module_exports(
mem::forget(exports);
}
#[no_mangle]
pub unsafe extern "C" fn wasm_module_imports(
module: &wasm_module_t,
out: &mut wasm_importtype_vec_t,
) {
let mut imports = module
.inner
.imports()
.map(Into::into)
.map(Box::new)
.map(Box::into_raw)
.collect::<Vec<*mut wasm_importtype_t>>();
debug_assert_eq!(imports.len(), imports.capacity());
out.size = imports.len();
out.data = imports.as_mut_ptr();
mem::forget(imports);
}
#[no_mangle]
pub unsafe extern "C" fn wasm_module_deserialize(
store_ptr: Option<NonNull<wasm_store_t>>,
@@ -1808,3 +1827,91 @@ impl From<&ExportType> for wasm_exporttype_t {
wasm_exporttype_t { name, extern_type }
}
}
// TODO: improve ownership in `importtype_t` (can we safely use `Box<wasm_name_t>` here?)
#[repr(C)]
#[allow(non_camel_case_types)]
pub struct wasm_importtype_t {
module: NonNull<wasm_name_t>,
name: NonNull<wasm_name_t>,
extern_type: NonNull<wasm_externtype_t>,
}
wasm_declare_boxed_vec!(importtype);
#[no_mangle]
pub extern "C" fn wasm_importtype_new(
module: NonNull<wasm_name_t>,
name: NonNull<wasm_name_t>,
extern_type: NonNull<wasm_externtype_t>,
) -> Box<wasm_importtype_t> {
Box::new(wasm_importtype_t {
name,
module,
extern_type,
})
}
#[no_mangle]
pub extern "C" fn wasm_importtype_module(et: &'static wasm_importtype_t) -> &'static wasm_name_t {
unsafe { et.module.as_ref() }
}
#[no_mangle]
pub extern "C" fn wasm_importtype_name(et: &'static wasm_importtype_t) -> &'static wasm_name_t {
unsafe { et.name.as_ref() }
}
#[no_mangle]
pub extern "C" fn wasm_importtype_type(
et: &'static wasm_importtype_t,
) -> &'static wasm_externtype_t {
unsafe { et.extern_type.as_ref() }
}
impl From<ImportType> for wasm_importtype_t {
fn from(other: ImportType) -> Self {
(&other).into()
}
}
impl From<&ImportType> for wasm_importtype_t {
fn from(other: &ImportType) -> Self {
// TODO: double check that freeing String as `Vec<u8>` is valid
let name = {
let mut heap_str: Box<str> = other.name().to_string().into_boxed_str();
let char_ptr = heap_str.as_mut_ptr();
let str_len = heap_str.bytes().len();
let name_inner = wasm_name_t {
size: str_len,
data: char_ptr,
};
Box::leak(heap_str);
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
};
// TODO: double check that freeing String as `Vec<u8>` is valid
let module = {
let mut heap_str: Box<str> = other.module().to_string().into_boxed_str();
let char_ptr = heap_str.as_mut_ptr();
let str_len = heap_str.bytes().len();
let name_inner = wasm_name_t {
size: str_len,
data: char_ptr,
};
Box::leak(heap_str);
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
};
let extern_type = {
let extern_type: wasm_externtype_t = other.ty().into();
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) }
};
wasm_importtype_t {
name,
module,
extern_type,
}
}
}

View File

@@ -228,7 +228,18 @@ pub unsafe extern "C" fn wasi_get_imports(
store: Option<NonNull<wasm_store_t>>,
module: &wasm_module_t,
wasi_env: &wasi_env_t,
) -> Option<Box<[Box<wasm_extern_t>]>> {
imports: *mut *mut wasm_extern_t,
) -> bool {
wasi_get_imports_inner(store, module, wasi_env, imports).is_some()
}
/// Takes ownership of `wasi_env_t`.
unsafe extern "C" fn wasi_get_imports_inner(
store: Option<NonNull<wasm_store_t>>,
module: &wasm_module_t,
wasi_env: &wasi_env_t,
imports: *mut *mut wasm_extern_t,
) -> Option<()> {
let store_ptr = store?.cast::<Store>();
let store = store_ptr.as_ref();
@@ -240,8 +251,7 @@ pub unsafe extern "C" fn wasi_get_imports(
let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version);
let mut extern_vec = vec![];
for it in module.inner.imports() {
for (i, it) in module.inner.imports().enumerate() {
let export = c_try!(import_object
.resolve_by_name(it.module(), it.name())
.ok_or_else(|| CApiError {
@@ -252,11 +262,15 @@ pub unsafe extern "C" fn wasi_get_imports(
),
}));
let inner = Extern::from_export(store, export);
extern_vec.push(Box::new(wasm_extern_t {
*imports.add(i) = Box::into_raw(Box::new(wasm_extern_t {
instance: None,
inner,
}));
}
Some(extern_vec.into_boxed_slice())
Some(())
}
/// Delete a `wasm_extern_t` allocated by the API.
#[no_mangle]
pub unsafe fn wasm_extern_delete(_item: Option<Box<wasm_extern_t>>) {}

View File

@@ -69,14 +69,20 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
const wasm_extern_t* const* imports = wasi_get_imports(store, module, wasi_env);
if (!imports) {
wasm_importtype_vec_t import_types;
wasm_module_imports(module, &import_types);
int num_imports = import_types.size;
wasm_extern_t** imports = malloc(num_imports * sizeof(wasm_extern_t*));
wasm_importtype_vec_delete(&import_types);
bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports);
if (!get_imports_result) {
printf("> Error getting WASI imports!\n");
print_wasmer_error();
return 1;
}
own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL);
wasm_instance_new(store, module, (const wasm_extern_t *const *) imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
print_wasmer_error();
@@ -131,6 +137,12 @@ int main(int argc, const char* argv[]) {
wasm_extern_vec_delete(&exports);
// NEEDS REVIEW:
for(int i = 0; i < num_imports; ++i) {
wasm_extern_delete(imports[i]);
}
free(imports);
// Shut down.
printf("Shutting down...\n");
wasi_env_delete(wasi_env);

View File

@@ -63,9 +63,10 @@ own wasi_env_t* wasi_env_new(own wasi_config_t*);
void wasi_env_delete(own wasi_env_t*);
// Get an array of imports that can be used to instantiate the given module.
own const wasm_extern_t* own const* wasi_get_imports(wasm_store_t* store,
bool wasi_get_imports(wasm_store_t* store,
wasm_module_t* module,
wasi_env_t* wasi_env);
wasi_env_t* wasi_env,
wasm_extern_t** imports);
// TODO: investigate removing this part of the API
// Set the memory in the `wasi_env_t` so that the WASI host functions can access WASI's memory.
@@ -86,6 +87,9 @@ size_t wasi_env_read_stderr(wasi_env_t* env,
// Get the version of WASI needed by the given Wasm module.
wasi_version_t wasi_get_wasi_version(wasm_module_t*);
// Delete a `wasm_extern_t` allocated by the API.
void wasm_extern_delete(wasm_extern_t*);
// TODO: figure out if we can do less duplication.
/**
* Gets the length in bytes of the last error if any.