Implement Exportable for NativeFunc

This commit is contained in:
Mark McCaskey
2020-06-08 16:07:22 -07:00
parent e2b6041a65
commit 8530e5eb55
9 changed files with 61 additions and 60 deletions

View File

@@ -1,11 +1,13 @@
use crate::externals::{Extern, Function, Global, Memory, Table}; use crate::externals::{Extern, Function, Global, Memory, Table};
use crate::import_object::LikeNamespace; use crate::import_object::LikeNamespace;
use crate::native::NativeFunc;
use indexmap::IndexMap; use indexmap::IndexMap;
use std::{ use std::{
iter::{ExactSizeIterator, FromIterator}, iter::{ExactSizeIterator, FromIterator},
sync::Arc, sync::Arc,
}; };
use thiserror::Error; use thiserror::Error;
use wasm_common::WasmTypeList;
use wasmer_runtime::Export; use wasmer_runtime::Export;
/// The `ExportError` can happen when trying to get a specific /// The `ExportError` can happen when trying to get a specific
@@ -89,7 +91,7 @@ impl Exports {
/// ///
/// If you want to get an export dynamically handling manually /// If you want to get an export dynamically handling manually
/// type checking manually, please use `get_extern`. /// type checking manually, please use `get_extern`.
pub fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> Result<&T, ExportError> { pub fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> Result<T, ExportError> {
match self.map.get(name) { match self.map.get(name) {
None => Err(ExportError::Missing(name.to_string())), None => Err(ExportError::Missing(name.to_string())),
Some(extern_) => T::get_self_from_extern(extern_), Some(extern_) => T::get_self_from_extern(extern_),
@@ -97,32 +99,36 @@ impl Exports {
} }
/// Get an export as a `Global`. /// Get an export as a `Global`.
pub fn get_global(&self, name: &str) -> Result<&Global, ExportError> { pub fn get_global(&self, name: &str) -> Result<Global, ExportError> {
self.get(name) self.get(name)
} }
/// Get an export as a `Memory`. /// Get an export as a `Memory`.
pub fn get_memory(&self, name: &str) -> Result<&Memory, ExportError> { pub fn get_memory(&self, name: &str) -> Result<Memory, ExportError> {
self.get(name) self.get(name)
} }
/// Get an export as a `Table`. /// Get an export as a `Table`.
pub fn get_table(&self, name: &str) -> Result<&Table, ExportError> { pub fn get_table(&self, name: &str) -> Result<Table, ExportError> {
self.get(name) self.get(name)
} }
/// Get an export as a `Func`. /// Get an export as a `Func`.
pub fn get_function(&self, name: &str) -> Result<&Function, ExportError> { pub fn get_function(&self, name: &str) -> Result<Function, ExportError> {
self.get(name) self.get(name)
} }
/* /// Get an export as a `NativeFunc`.
/// Get an export as a `Func`. pub fn get_native_function<Args, Rets>(
pub fn get_native_function::<Args, Rets>(&self, name: &str) -> Result<&NativeFunction, ExportError> { &self,
// TODO: name: &str,
//self.get(name) ) -> Result<NativeFunc<Args, Rets>, ExportError>
where
Args: WasmTypeList,
Rets: WasmTypeList,
{
self.get(name)
} }
*/
/// Get an export as an `Extern`. /// Get an export as an `Extern`.
pub fn get_extern(&self, name: &str) -> Option<&Extern> { pub fn get_extern(&self, name: &str) -> Option<&Extern> {
@@ -250,5 +256,5 @@ pub trait Exportable<'a>: Sized {
/// from an [`Instance`] by name. /// from an [`Instance`] by name.
/// ///
/// [`Instance`]: crate::Instance /// [`Instance`]: crate::Instance
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError>; fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError>;
} }

View File

@@ -317,9 +317,9 @@ impl<'a> Exportable<'a> for Function {
fn to_export(&self) -> Export { fn to_export(&self) -> Export {
self.exported.clone().into() self.exported.clone().into()
} }
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
match _extern { match _extern {
Extern::Function(func) => Ok(func), Extern::Function(func) => Ok(func.clone()),
_ => Err(ExportError::IncompatibleType), _ => Err(ExportError::IncompatibleType),
} }
} }

View File

@@ -130,9 +130,9 @@ impl<'a> Exportable<'a> for Global {
self.exported.clone().into() self.exported.clone().into()
} }
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
match _extern { match _extern {
Extern::Global(global) => Ok(global), Extern::Global(global) => Ok(global.clone()),
_ => Err(ExportError::IncompatibleType), _ => Err(ExportError::IncompatibleType),
} }
} }

View File

@@ -137,9 +137,9 @@ impl<'a> Exportable<'a> for Memory {
fn to_export(&self) -> Export { fn to_export(&self) -> Export {
self.exported.clone().into() self.exported.clone().into()
} }
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
match _extern { match _extern {
Extern::Memory(memory) => Ok(memory), Extern::Memory(memory) => Ok(memory.clone()),
_ => Err(ExportError::IncompatibleType), _ => Err(ExportError::IncompatibleType),
} }
} }

View File

@@ -51,9 +51,9 @@ impl<'a> Exportable<'a> for Extern {
} }
} }
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
// Since this is already an extern, we can just return it. // Since this is already an extern, we can just return it.
Ok(_extern) Ok(_extern.clone())
} }
} }

View File

@@ -158,9 +158,9 @@ impl<'a> Exportable<'a> for Table {
fn to_export(&self) -> Export { fn to_export(&self) -> Export {
self.exported.clone().into() self.exported.clone().into()
} }
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
match _extern { match _extern {
Extern::Table(table) => Ok(table), Extern::Table(table) => Ok(table.clone()),
_ => Err(ExportError::IncompatibleType), _ => Err(ExportError::IncompatibleType),
} }
} }

View File

@@ -4,10 +4,10 @@ use std::marker::PhantomData;
use crate::exports::{ExportError, Exportable}; use crate::exports::{ExportError, Exportable};
use crate::externals::function::{FunctionDefinition, WasmFunctionDefinition}; use crate::externals::function::{FunctionDefinition, WasmFunctionDefinition};
use crate::{Extern, Function, FunctionType, RuntimeError, Store}; use crate::{Extern, Function, FunctionType, Store};
use wasm_common::{NativeWasmType, WasmExternType, WasmTypeList}; use wasm_common::{NativeWasmType, WasmExternType, WasmTypeList};
use wasmer_runtime::{ use wasmer_runtime::{
wasmer_call_trampoline, ExportFunction, VMContext, VMFunctionBody, VMFunctionKind, VMTrampoline, wasmer_call_trampoline, Export, ExportFunction, VMContext, VMFunctionBody, VMFunctionKind,
}; };
#[derive(Clone)] #[derive(Clone)]
@@ -15,29 +15,6 @@ pub struct UnprovidedArgs;
#[derive(Clone)] #[derive(Clone)]
pub struct UnprovidedRets; pub struct UnprovidedRets;
/// This is just an empty trait to constrict that types that
/// can be put into the third/fourth (depending if you include lifetimes)
/// of the `NativeFunc` struct.
pub trait Kind {}
/// TODO(lachlan): Naming TBD.
/// This contains the trampoline and invoke functions for a specific signature,
/// as well as the environment that the invoke function may or may not require.
#[derive(Copy, Clone)]
pub struct Wasm {
pub(crate) trampoline: VMTrampoline,
//pub(crate) invoke: Invoke,
//pub(crate) invoke_env: Option<NonNull<c_void>>,
}
impl Kind for Wasm {}
/// This type, as part of the `NativeFunc` type signature, represents a function that is created
/// by the host.
pub struct Host(());
impl Kind for Host {}
pub struct NativeFunc<'a, Args = UnprovidedArgs, Rets = UnprovidedRets> { pub struct NativeFunc<'a, Args = UnprovidedArgs, Rets = UnprovidedRets> {
definition: FunctionDefinition, definition: FunctionDefinition,
store: Store, store: Store,
@@ -69,35 +46,53 @@ impl<'a, Args, Rets> NativeFunc<'a, Args, Rets> {
} }
} }
/* impl<'a, Args, Rets> Exportable<'a> for NativeFunc<'a, Args, Rets>
impl<'a, Args, Rets> Exportable for NativeFunc<'a, Args, Rets>
where where
Args: WasmTypeList, Args: WasmTypeList,
Rets: WasmTypeList, Rets: WasmTypeList,
{ {
fn to_export(&self) -> Export { fn to_export(&self) -> Export {
todo!("implement this") let ef: ExportFunction = self.into();
ef.into()
} }
// Cannot be implemented because of the return type `&Self` TODO: // Cannot be implemented because of the return type `&Self` TODO:
fn get_self_from_extern(extern_: &'a Extern) -> Result<&'a Self, ExportError> { fn get_self_from_extern(extern_: &'a Extern) -> Result<Self, ExportError> {
match extern_ { match extern_ {
// TODO: review error return type in failure of `f.native()` // TODO: review error return type in failure of `f.native()`
Extern::Function(f) => f.native().ok_or_else(|| ExportError::IncompatibleType), Extern::Function(f) => f
.clone()
.native()
.ok_or_else(|| ExportError::IncompatibleType),
_ => Err(ExportError::IncompatibleType), _ => Err(ExportError::IncompatibleType),
} }
} }
} }
*/
impl<'a, Args, Rets> From<&NativeFunc<'a, Args, Rets>> for ExportFunction
where
Args: WasmTypeList,
Rets: WasmTypeList,
{
fn from(other: &NativeFunc<'a, Args, Rets>) -> Self {
let signature = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
Self {
address: other.address,
vmctx: other.vmctx,
signature,
kind: other.arg_kind,
}
}
}
impl<'a, Args, Rets> From<NativeFunc<'a, Args, Rets>> for Function impl<'a, Args, Rets> From<NativeFunc<'a, Args, Rets>> for Function
where where
Args: WasmTypeList, Args: WasmTypeList,
Rets: WasmTypeList, Rets: WasmTypeList,
{ {
fn from(other: NativeFunc<'a, Args, Rets>) -> Function { fn from(other: NativeFunc<'a, Args, Rets>) -> Self {
let signature = FunctionType::new(Args::wasm_types(), Rets::wasm_types()); let signature = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
Function { Self {
store: other.store, store: other.store,
definition: other.definition, definition: other.definition,
owned_by_store: true, // todo owned_by_store: true, // todo

View File

@@ -111,10 +111,10 @@ impl Wasi {
let instance = Instance::new(&module, &import_object)?; let instance = Instance::new(&module, &import_object)?;
let memory: &Memory = instance.exports.get("memory")?; let memory: Memory = instance.exports.get("memory")?;
wasi_env.set_memory(memory); wasi_env.set_memory(&memory);
let start: &Function = instance.exports.get("_start")?; let start: Function = instance.exports.get("_start")?;
start start
.call(&[]) .call(&[])

View File

@@ -341,7 +341,7 @@ impl Wast {
args: &[Val], args: &[Val],
) -> Result<Vec<Val>> { ) -> Result<Vec<Val>> {
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?; let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
let func: &Function = instance.exports.get(field)?; let func: Function = instance.exports.get(field)?;
match func.call(args) { match func.call(args) {
Ok(result) => Ok(result.into()), Ok(result) => Ok(result.into()),
Err(e) => Err(e.into()), Err(e) => Err(e.into()),
@@ -351,7 +351,7 @@ impl Wast {
/// Get the value of an exported global from an instance. /// Get the value of an exported global from an instance.
fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result<Vec<Val>> { fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result<Vec<Val>> {
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?; let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
let global: &Global = instance.exports.get(field)?; let global: Global = instance.exports.get(field)?;
Ok(vec![global.get()]) Ok(vec![global.get()])
} }