Apply various fixes to get the C API working

24% of tests are passing now!
This commit is contained in:
Mark McCaskey
2020-05-07 14:02:13 -07:00
parent 68bf175ddb
commit 480ecd2cda
17 changed files with 167 additions and 165 deletions

1
Cargo.lock generated
View File

@@ -1710,6 +1710,7 @@ name = "wasmer-runtime-c-api"
version = "0.16.2" version = "0.16.2"
dependencies = [ dependencies = [
"cbindgen", "cbindgen",
"lazy_static",
"libc", "libc",
"wasmer", "wasmer",
"wasmer-wasi", "wasmer-wasi",

View File

@@ -6,15 +6,15 @@ use wasmer_engine::Engine;
#[derive(Clone)] #[derive(Clone)]
pub struct Store { pub struct Store {
engine: Arc<dyn Engine>, engine: Arc<dyn Engine + Send + Sync>,
} }
impl Store { impl Store {
pub fn new(engine: Arc<dyn Engine>) -> Store { pub fn new(engine: Arc<dyn Engine + Send + Sync>) -> Store {
Store { engine } Store { engine }
} }
pub fn engine(&self) -> &Arc<dyn Engine> { pub fn engine(&self) -> &Arc<dyn Engine + Send + Sync> {
&self.engine &self.engine
} }
@@ -37,28 +37,30 @@ impl Default for Store {
// sure this function doesn't emit a compile error even if // sure this function doesn't emit a compile error even if
// more than one compiler is enabled. // more than one compiler is enabled.
#[allow(unreachable_code)] #[allow(unreachable_code)]
fn get_config() -> Box<dyn CompilerConfig> { fn get_config() -> Arc<dyn CompilerConfig + Send + Sync> {
#[cfg(feature = "cranelift")] #[cfg(feature = "cranelift")]
return Box::new(wasmer_compiler_cranelift::CraneliftConfig::default()); return Arc::new(wasmer_compiler_cranelift::CraneliftConfig::default());
#[cfg(feature = "llvm")] #[cfg(feature = "llvm")]
return Box::new(wasmer_compiler_llvm::LLVMConfig::default()); return Arc::new(wasmer_compiler_llvm::LLVMConfig::default());
#[cfg(feature = "singlepass")] #[cfg(feature = "singlepass")]
return Box::new(wasmer_compiler_singlepass::SinglepassConfig::default()); return Arc::new(wasmer_compiler_singlepass::SinglepassConfig::default());
} }
#[allow(unreachable_code)] #[allow(unreachable_code)]
fn get_engine(config: Box<dyn CompilerConfig>) -> Arc<dyn Engine> { fn get_engine(
config: Arc<dyn CompilerConfig + Send + Sync>,
) -> Arc<dyn Engine + Send + Sync> {
let tunables = Tunables::for_target(config.target().triple()); let tunables = Tunables::for_target(config.target().triple());
#[cfg(feature = "jit")] #[cfg(feature = "jit")]
return Arc::new(wasmer_engine_jit::JITEngine::new(&config, tunables)); return Arc::new(wasmer_engine_jit::JITEngine::new(&*config, tunables));
} }
let config = get_config(); let config = get_config();
let engine = get_engine(config); let engine = get_engine(config);
Store::new(config) Store::new(engine)
} }
} }

View File

@@ -179,7 +179,7 @@ impl CompilerConfig for CraneliftConfig {
} }
/// Transform it into the compiler /// Transform it into the compiler
fn compiler(&self) -> Box<dyn Compiler> { fn compiler(&self) -> Box<dyn Compiler + Send> {
Box::new(CraneliftCompiler::new(&self)) Box::new(CraneliftCompiler::new(&self))
} }
} }

View File

@@ -142,7 +142,7 @@ impl CompilerConfig for LLVMConfig {
} }
/// Transform it into the compiler /// Transform it into the compiler
fn compiler(&self) -> Box<dyn Compiler> { fn compiler(&self) -> Box<dyn Compiler + Send> {
Box::new(LLVMCompiler::new(&self)) Box::new(LLVMCompiler::new(&self))
} }
} }

View File

@@ -27,7 +27,7 @@ pub trait CompilerConfig {
fn target(&self) -> &Target; fn target(&self) -> &Target;
/// Gets the custom compiler config /// Gets the custom compiler config
fn compiler(&self) -> Box<dyn Compiler>; fn compiler(&self) -> Box<dyn Compiler + Send>;
} }
/// An implementation of a Compiler from parsed WebAssembly module to Compiled native code. /// An implementation of a Compiler from parsed WebAssembly module to Compiled native code.

View File

@@ -1,9 +1,8 @@
//! JIT compilation. //! JIT compilation.
use crate::{CodeMemory, CompiledModule}; use crate::{CodeMemory, CompiledModule};
use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::{Arc, Mutex};
use wasm_common::entity::PrimaryMap; use wasm_common::entity::PrimaryMap;
use wasm_common::{FunctionType, LocalFunctionIndex, MemoryIndex, SignatureIndex, TableIndex}; use wasm_common::{FunctionType, LocalFunctionIndex, MemoryIndex, SignatureIndex, TableIndex};
use wasmer_compiler::{Compilation, CompileError, FunctionBody, Target}; use wasmer_compiler::{Compilation, CompileError, FunctionBody, Target};
@@ -21,8 +20,8 @@ use wasmer_runtime::{
/// A WebAssembly `JIT` Engine. /// A WebAssembly `JIT` Engine.
#[derive(Clone)] #[derive(Clone)]
pub struct JITEngine { pub struct JITEngine {
inner: Arc<RefCell<JITEngineInner>>, inner: Arc<Mutex<JITEngineInner>>,
tunables: Arc<Box<dyn Tunables>>, tunables: Arc<dyn Tunables + Send + Sync>,
} }
impl JITEngine { impl JITEngine {
@@ -30,19 +29,22 @@ impl JITEngine {
/// Create a new `JITEngine` with the given config /// Create a new `JITEngine` with the given config
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
pub fn new<C: CompilerConfig>(config: &C, tunables: impl Tunables + 'static) -> Self pub fn new<C: CompilerConfig>(
config: &C,
tunables: impl Tunables + 'static + Send + Sync,
) -> Self
where where
C: ?Sized, C: ?Sized,
{ {
let compiler = config.compiler(); let compiler = config.compiler();
Self { Self {
inner: Arc::new(RefCell::new(JITEngineInner { inner: Arc::new(Mutex::new(JITEngineInner {
compiler: Some(compiler), compiler: Some(compiler),
trampolines: HashMap::new(), trampolines: HashMap::new(),
code_memory: CodeMemory::new(), code_memory: CodeMemory::new(),
signatures: SignatureRegistry::new(), signatures: SignatureRegistry::new(),
})), })),
tunables: Arc::new(Box::new(tunables)), tunables: Arc::new(tunables),
} }
} }
@@ -59,25 +61,25 @@ impl JITEngine {
/// ///
/// Headless engines can't compile or validate any modules, /// Headless engines can't compile or validate any modules,
/// they just take already processed Modules (via `Module::serialize`). /// they just take already processed Modules (via `Module::serialize`).
pub fn headless(tunables: impl Tunables + 'static) -> Self { pub fn headless(tunables: impl Tunables + 'static + Send + Sync) -> Self {
Self { Self {
inner: Arc::new(RefCell::new(JITEngineInner { inner: Arc::new(Mutex::new(JITEngineInner {
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
compiler: None, compiler: None,
trampolines: HashMap::new(), trampolines: HashMap::new(),
code_memory: CodeMemory::new(), code_memory: CodeMemory::new(),
signatures: SignatureRegistry::new(), signatures: SignatureRegistry::new(),
})), })),
tunables: Arc::new(Box::new(tunables)), tunables: Arc::new(tunables),
} }
} }
pub(crate) fn compiler(&self) -> std::cell::Ref<'_, JITEngineInner> { pub(crate) fn compiler(&self) -> std::sync::MutexGuard<'_, JITEngineInner> {
self.inner.borrow() self.inner.lock().unwrap()
} }
pub(crate) fn compiler_mut(&self) -> std::cell::RefMut<'_, JITEngineInner> { pub(crate) fn compiler_mut(&self) -> std::sync::MutexGuard<'_, JITEngineInner> {
self.inner.borrow_mut() self.inner.lock().unwrap()
} }
/// Check if the provided bytes look like a serialized /// Check if the provided bytes look like a serialized
@@ -90,7 +92,7 @@ impl JITEngine {
impl Engine for JITEngine { impl Engine for JITEngine {
/// Get the tunables /// Get the tunables
fn tunables(&self) -> &dyn Tunables { fn tunables(&self) -> &dyn Tunables {
&**self.tunables &*self.tunables
} }
/// Register a signature /// Register a signature
@@ -160,7 +162,7 @@ impl Engine for JITEngine {
pub struct JITEngineInner { pub struct JITEngineInner {
/// The compiler /// The compiler
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
compiler: Option<Box<dyn Compiler>>, compiler: Option<Box<dyn Compiler + Send>>,
/// Pointers to trampoline functions used to enter particular signatures /// Pointers to trampoline functions used to enter particular signatures
trampolines: HashMap<VMSharedSignatureIndex, VMTrampoline>, trampolines: HashMap<VMSharedSignatureIndex, VMTrampoline>,
/// The code memory is responsible of publishing the compiled /// The code memory is responsible of publishing the compiled

View File

@@ -15,6 +15,7 @@ readme = "README.md"
crate-type = ["cdylib", "staticlib"] crate-type = ["cdylib", "staticlib"]
[dependencies] [dependencies]
lazy_static = "1"
libc = "0.2.60" libc = "0.2.60"
# for generating code in the same way thot the wasm-c-api does # for generating code in the same way thot the wasm-c-api does
# Commented out for now until we can find a solution to the exported function problem # Commented out for now until we can find a solution to the exported function problem
@@ -22,6 +23,7 @@ libc = "0.2.60"
[dependencies.wasmer] [dependencies.wasmer]
default-features = false default-features = false
features = ["compiler", "engine", "jit", "cranelift"]
path = "../api" path = "../api"
version = "0.16.2" version = "0.16.2"

View File

@@ -21,14 +21,13 @@ pub unsafe extern "C" fn wasmer_global_new(
value: wasmer_value_t, value: wasmer_value_t,
mutable: bool, mutable: bool,
) -> *mut wasmer_global_t { ) -> *mut wasmer_global_t {
let global_store = todo!("Implement global store"); let store = crate::get_global_store();
/*let global = if mutable { let global = if mutable {
Global::new_mut(value.into()) Global::new_mut(store, value.into())
} else { } else {
Global::new(value.into()) Global::new(store, value.into())
}; };
Box::into_raw(Box::new(global)) as *mut wasmer_global_t Box::into_raw(Box::new(global)) as *mut wasmer_global_t
*/
} }
/// Gets the value stored by the given Global /// Gets the value stored by the given Global

View File

@@ -2,6 +2,7 @@ use super::*;
use crate::get_slice_checked; use crate::get_slice_checked;
use libc::c_uchar; use libc::c_uchar;
use std::{path::PathBuf, ptr, str}; use std::{path::PathBuf, ptr, str};
use wasmer::{Memory, MemoryType};
use wasmer_wasi as wasi; use wasmer_wasi as wasi;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@@ -148,10 +149,10 @@ fn wasmer_wasi_generate_import_object_inner(
preopened_file_list: &[wasmer_byte_array], preopened_file_list: &[wasmer_byte_array],
mapped_dir_list: &[wasmer_wasi_map_dir_entry_t], mapped_dir_list: &[wasmer_wasi_map_dir_entry_t],
) -> Result<*mut wasmer_import_object_t, str::Utf8Error> { ) -> Result<*mut wasmer_import_object_t, str::Utf8Error> {
todo!("wasmer_wasi_generate_import_object_inner: blocked on global store") todo!("Arg and env parsing need to be done here; this logic already exists and it's important to get it right, so we should probably reorganize code to make it easier to do the right thing.")
/* /*
let arg_vec = arg_list.iter().map(|arg| unsafe { arg.as_vec() }).collect(); let arg_vec: Vec<_> = arg_list.iter().map(|arg| unsafe { arg.as_vec() }).collect();
let env_vec = env_list let env_vec: Vec<_> = env_list
.iter() .iter()
.map(|env_var| unsafe { env_var.as_vec() }) .map(|env_var| unsafe { env_var.as_vec() })
.collect(); .collect();
@@ -171,12 +172,28 @@ fn wasmer_wasi_generate_import_object_inner(
_ => panic!("Version {:?} is invalid.", version), _ => panic!("Version {:?} is invalid.", version),
}; };
let import_object = Box::new(wasi::generate_import_object_for_version( let store = crate::get_global_store();
let mut wasi_state_builder = wasi::WasiState::new(
arg_vec
.first()
.unwrap_or_else("wasmer-wasi-default-program-name"),
);
wasi_state_builder
.args(&arg_vec[1..])
.envs(env_vec)
.preopen_dirs(po_file_vec)?
.map_dirs(mapped_dir_vec)?;
let wasi_state = wasi_state_builder.build().unwrap();
let mut wasi_env = wasi::WasiEnv::new(wasi_state);
let memory_type = MemoryType::new(0, None, false);
let memory = Memory::new(store, memory_type);
wasi_env.set_memory(&memory);
let import_object = Box::new(wasi::generate_import_object_from_env(
store,
&mut wasi_env,
version, version,
arg_vec,
env_vec,
po_file_vec,
mapped_dir_vec,
)); ));
Ok(Box::into_raw(import_object) as *mut wasmer_import_object_t) Ok(Box::into_raw(import_object) as *mut wasmer_import_object_t)
*/ */
@@ -190,20 +207,22 @@ fn wasmer_wasi_generate_import_object_inner(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasmer_wasi_generate_default_import_object() -> *mut wasmer_import_object_t pub unsafe extern "C" fn wasmer_wasi_generate_default_import_object() -> *mut wasmer_import_object_t
{ {
/* let mut wasi_state_builder = wasi::WasiState::new(); let store = crate::get_global_store();
let mut wasi_state_builder = wasi::WasiState::new("wasmer-wasi-default-program-name");
let wasi_state = wasi_state_builder.build().unwrap(); let wasi_state = wasi_state_builder.build().unwrap();
let mut wasi_env = WasiEnv::new(wasi_state); let mut wasi_env = wasi::WasiEnv::new(wasi_state);
// this API will now leak a `Memory` // this API will now leak a `Memory`
let memory = todo!("get a memory"); let memory_type = MemoryType::new(0, None, false);
let store = todo!("somehow get a store"); let memory = Memory::new(store, memory_type);
wasi_env.set_memory(memory); wasi_env.set_memory(&memory);
let import_object = Box::new(wasi::generate_import_object_from_env(store, )); // TODO(mark): review lifetime of `Memory` here
let import_object = Box::new(wasi::generate_import_object_from_env(
store,
&mut wasi_env,
wasi::WasiVersion::Latest,
));
Box::into_raw(import_object) as *mut wasmer_import_object_t Box::into_raw(import_object) as *mut wasmer_import_object_t
*/
unimplemented!(
"This function can't be implemented until more backwards compatibilty code exists"
);
} }
#[cfg(test)] #[cfg(test)]

View File

@@ -2,7 +2,7 @@
use crate::{ use crate::{
error::{update_last_error, CApiError}, error::{update_last_error, CApiError},
export::{wasmer_exports_t, NamedExports}, export::{wasmer_exports_t, wasmer_import_export_kind, NamedExports},
import::wasmer_import_t, import::wasmer_import_t,
memory::wasmer_memory_t, memory::wasmer_memory_t,
value::wasmer_value_t, value::wasmer_value_t,
@@ -10,10 +10,12 @@ use crate::{
wasmer_result_t, wasmer_result_t,
}; };
use libc::{c_char, c_int, c_void}; use libc::{c_char, c_int, c_void};
//use std::{collections::HashMap, ptr, slice}; use std::collections::HashMap;
use std::ptr; use std::ptr;
//use wasmer::{ExportType, Exports, Global, ImportObject, Instance, Memory, Table}; use std::slice;
use wasmer::{ExportType, Instance}; use wasmer::{
ExportType, Exports, Extern, Function, Global, ImportObject, Instance, Memory, Module, Table,
};
/// Opaque pointer to a `wasmer_runtime::Instance` value in Rust. /// Opaque pointer to a `wasmer_runtime::Instance` value in Rust.
/// ///
@@ -108,8 +110,6 @@ pub unsafe extern "C" fn wasmer_instantiate(
}); });
return wasmer_result_t::WASMER_ERROR; return wasmer_result_t::WASMER_ERROR;
} }
todo!("Figure out how instantiating works")
/*
let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize); let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize);
let mut import_object = ImportObject::new(); let mut import_object = ImportObject::new();
let mut namespaces = HashMap::new(); let mut namespaces = HashMap::new();
@@ -145,19 +145,19 @@ pub unsafe extern "C" fn wasmer_instantiate(
let export = match import.tag { let export = match import.tag {
wasmer_import_export_kind::WASM_MEMORY => { wasmer_import_export_kind::WASM_MEMORY => {
let mem = import.value.memory as *mut Memory; let mem = import.value.memory as *mut Memory;
Export::Memory((&*mem).clone()) Extern::Memory((&*mem).clone())
} }
wasmer_import_export_kind::WASM_FUNCTION => { wasmer_import_export_kind::WASM_FUNCTION => {
let func_export = import.value.func as *mut Export; let func_export = import.value.func as *mut Function;
(&*func_export).clone() Extern::Function((&*func_export).clone())
} }
wasmer_import_export_kind::WASM_GLOBAL => { wasmer_import_export_kind::WASM_GLOBAL => {
let global = import.value.global as *mut Global; let global = import.value.global as *mut Global;
Export::Global((&*global).clone()) Extern::Global((&*global).clone())
} }
wasmer_import_export_kind::WASM_TABLE => { wasmer_import_export_kind::WASM_TABLE => {
let table = import.value.table as *mut Table; let table = import.value.table as *mut Table;
Export::Table((&*table).clone()) Extern::Table((&*table).clone())
} }
}; };
namespace.insert(import_name, export); namespace.insert(import_name, export);
@@ -167,9 +167,9 @@ pub unsafe extern "C" fn wasmer_instantiate(
} }
let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize);
let store = todo!("Get global store"); let store = crate::get_global_store();
*/
/*let module_result = Module::compile(store, bytes); let module_result = Module::from_binary(store, bytes);
let module = match module_result { let module = match module_result {
Ok(module) => module, Ok(module) => module,
Err(error) => { Err(error) => {
@@ -177,7 +177,8 @@ pub unsafe extern "C" fn wasmer_instantiate(
return wasmer_result_t::WASMER_ERROR; return wasmer_result_t::WASMER_ERROR;
} }
}; };
let result = module.instantiate(&import_object); // TODO(mark): module is being freed here? This looks like a mistake
let result = Instance::new(&module, &import_object);
let new_instance = match result { let new_instance = match result {
Ok(instance) => instance, Ok(instance) => instance,
Err(error) => { Err(error) => {
@@ -187,7 +188,6 @@ pub unsafe extern "C" fn wasmer_instantiate(
}; };
*instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t;
wasmer_result_t::WASMER_OK wasmer_result_t::WASMER_OK
*/
} }
/// Returns the instance context. Learn more by looking at the /// Returns the instance context. Learn more by looking at the

View File

@@ -92,6 +92,9 @@
unreachable_patterns unreachable_patterns
)] )]
#[macro_use]
extern crate lazy_static;
pub mod error; pub mod error;
pub mod export; pub mod export;
pub mod global; pub mod global;
@@ -108,6 +111,8 @@ TODO: reenable `trampoline` module when the refactor gains feature parity with W
pub mod trampoline;*/ pub mod trampoline;*/
pub mod value; pub mod value;
use std::sync::Arc;
/// The `wasmer_result_t` enum is a type that represents either a /// The `wasmer_result_t` enum is a type that represents either a
/// success, or a failure. /// success, or a failure.
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@@ -179,3 +184,11 @@ pub(crate) unsafe fn get_slice_checked<'a, T>(ptr: *const T, len: usize) -> &'a
std::slice::from_raw_parts(ptr, len) std::slice::from_raw_parts(ptr, len)
} }
} }
lazy_static! {
pub(crate) static ref GLOBAL_STORE: Arc<wasmer::Store> = Arc::new(wasmer::Store::default());
}
pub(crate) fn get_global_store() -> &'static wasmer::Store {
&*GLOBAL_STORE
}

View File

@@ -5,7 +5,7 @@ use crate::{
wasmer_limits_t, wasmer_result_t, wasmer_limits_t, wasmer_result_t,
}; };
use std::{cell::Cell, ptr}; use std::{cell::Cell, ptr};
use wasmer::{Bytes, Memory, Pages}; use wasmer::{Bytes, Memory, MemoryType, Pages};
/// Opaque pointer to a `wasmer_runtime::Memory` value in Rust. /// Opaque pointer to a `wasmer_runtime::Memory` value in Rust.
/// ///
@@ -62,25 +62,16 @@ pub unsafe extern "C" fn wasmer_memory_new(
memory: *mut *mut wasmer_memory_t, memory: *mut *mut wasmer_memory_t,
limits: wasmer_limits_t, limits: wasmer_limits_t,
) -> wasmer_result_t { ) -> wasmer_result_t {
unimplemented!("wasmer_memory_new needs the global store")
/*
let max = if limits.max.has_some { let max = if limits.max.has_some {
Some(Pages(limits.max.some)) Some(Pages(limits.max.some))
} else { } else {
None None
}; };
let store = crate::get_global_store();
let desc = MemoryType::new(Pages(limits.min), max, false); let desc = MemoryType::new(Pages(limits.min), max, false);
let result = Memory::new(desc); let new_memory = Memory::new(store, desc);
let new_memory = match result {
Ok(memory) => memory,
Err(error) => {
update_last_error(error);
return wasmer_result_t::WASMER_ERROR;
}
};
*memory = Box::into_raw(Box::new(new_memory)) as *mut wasmer_memory_t; *memory = Box::into_raw(Box::new(new_memory)) as *mut wasmer_memory_t;
wasmer_result_t::WASMER_OK wasmer_result_t::WASMER_OK
*/
} }
/// Grows a memory by the given number of pages (of 65Kb each). /// Grows a memory by the given number of pages (of 65Kb each).

View File

@@ -2,18 +2,15 @@
use crate::{ use crate::{
error::{update_last_error, CApiError}, error::{update_last_error, CApiError},
//export::wasmer_import_export_kind, export::wasmer_import_export_kind,
import::{wasmer_import_object_t, wasmer_import_t}, import::{wasmer_import_object_t, wasmer_import_t},
instance::wasmer_instance_t, instance::wasmer_instance_t,
wasmer_byte_array, wasmer_byte_array, wasmer_result_t,
wasmer_result_t,
}; };
use libc::c_int; use libc::c_int;
use std::collections::HashMap;
use std::slice; use std::slice;
//use wasmer::compiler::{compile, default_compiler}; use wasmer::{Exports, Extern, Function, Global, ImportObject, Instance, Memory, Module, Table};
//use wasmer::{Exports, Global, ImportObject, Module, Exports, Table};
use wasmer::Module;
//use wasmer_runtime_core::{cache::Artifact, load_cache_with};
#[repr(C)] #[repr(C)]
pub struct wasmer_module_t; pub struct wasmer_module_t;
@@ -34,11 +31,9 @@ pub unsafe extern "C" fn wasmer_compile(
wasm_bytes: *mut u8, wasm_bytes: *mut u8,
wasm_bytes_len: u32, wasm_bytes_len: u32,
) -> wasmer_result_t { ) -> wasmer_result_t {
unimplemented!("Blocked on global store");
/*
let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize);
let store = todo!("implement global store"); let store = crate::get_global_store();
let result = Module::compile(store, bytes); let result = Module::from_binary(store, bytes);
let new_module = match result { let new_module = match result {
Ok(instance) => instance, Ok(instance) => instance,
Err(error) => { Err(error) => {
@@ -48,7 +43,6 @@ pub unsafe extern "C" fn wasmer_compile(
}; };
*module = Box::into_raw(Box::new(new_module)) as *mut wasmer_module_t; *module = Box::into_raw(Box::new(new_module)) as *mut wasmer_module_t;
wasmer_result_t::WASMER_OK wasmer_result_t::WASMER_OK
*/
} }
/// Validates a sequence of bytes hoping it represents a valid WebAssembly module. /// Validates a sequence of bytes hoping it represents a valid WebAssembly module.
@@ -73,8 +67,8 @@ pub unsafe extern "C" fn wasmer_validate(wasm_bytes: *const u8, wasm_bytes_len:
let bytes: &[u8] = slice::from_raw_parts(wasm_bytes, wasm_bytes_len as usize); let bytes: &[u8] = slice::from_raw_parts(wasm_bytes, wasm_bytes_len as usize);
let store = todo!("implement global store"); let store = crate::get_global_store();
//Module::validate(store, bytes).is_ok() Module::validate(store, bytes).is_ok()
} }
/// Creates a new Instance from the given module and imports. /// Creates a new Instance from the given module and imports.
@@ -91,7 +85,6 @@ pub unsafe extern "C" fn wasmer_module_instantiate(
imports: *mut wasmer_import_t, imports: *mut wasmer_import_t,
imports_len: c_int, imports_len: c_int,
) -> wasmer_result_t { ) -> wasmer_result_t {
/*
let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize); let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize);
let mut import_object = ImportObject::new(); let mut import_object = ImportObject::new();
let mut namespaces = HashMap::new(); let mut namespaces = HashMap::new();
@@ -122,27 +115,23 @@ pub unsafe extern "C" fn wasmer_module_instantiate(
}; };
let namespace = namespaces.entry(module_name).or_insert_with(Exports::new); let namespace = namespaces.entry(module_name).or_insert_with(Exports::new);
*/
todo!("figure out how to instantiate")
/*
let export = match import.tag { let export = match import.tag {
wasmer_import_export_kind::WASM_MEMORY => { wasmer_import_export_kind::WASM_MEMORY => {
let mem = import.value.memory as *mut Memory; let mem = import.value.memory as *mut Memory;
Export::Memory((&*mem).clone()) Extern::Memory((&*mem).clone())
} }
wasmer_import_export_kind::WASM_FUNCTION => { wasmer_import_export_kind::WASM_FUNCTION => {
let func_export = import.value.func as *mut Export; let func_export = import.value.func as *mut Function;
(&*func_export).clone() Extern::Function((&*func_export).clone())
} }
wasmer_import_export_kind::WASM_GLOBAL => { wasmer_import_export_kind::WASM_GLOBAL => {
let global = import.value.global as *mut Global; let global = import.value.global as *mut Global;
Export::Global((&*global).clone()) Extern::Global((&*global).clone())
} }
wasmer_import_export_kind::WASM_TABLE => { wasmer_import_export_kind::WASM_TABLE => {
let table = import.value.table as *mut Table; let table = import.value.table as *mut Table;
Export::Table((&*table).clone()) Extern::Table((&*table).clone())
} }
}; };
namespace.insert(import_name, export); namespace.insert(import_name, export);
@@ -152,7 +141,7 @@ pub unsafe extern "C" fn wasmer_module_instantiate(
} }
let module = &*(module as *const Module); let module = &*(module as *const Module);
let new_instance = match module.instantiate(&import_object) { let new_instance = match Instance::new(module, &import_object) {
Ok(instance) => instance, Ok(instance) => instance,
Err(error) => { Err(error) => {
update_last_error(error); update_last_error(error);
@@ -162,7 +151,6 @@ pub unsafe extern "C" fn wasmer_module_instantiate(
*instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t;
wasmer_result_t::WASMER_OK wasmer_result_t::WASMER_OK
*/
} }
/// Given: /// Given:
@@ -176,12 +164,10 @@ pub unsafe extern "C" fn wasmer_module_import_instantiate(
module: *const wasmer_module_t, module: *const wasmer_module_t,
import_object: *const wasmer_import_object_t, import_object: *const wasmer_import_object_t,
) -> wasmer_result_t { ) -> wasmer_result_t {
todo!("Figure out how to instanitate")
/*
let import_object: &ImportObject = &*(import_object as *const ImportObject); let import_object: &ImportObject = &*(import_object as *const ImportObject);
let module: &Module = &*(module as *const Module); let module: &Module = &*(module as *const Module);
let new_instance: Instance = match module.instantiate(import_object) { let new_instance: Instance = match Instance::new(module, import_object) {
Ok(instance) => instance, Ok(instance) => instance,
Err(error) => { Err(error) => {
update_last_error(error); update_last_error(error);
@@ -191,7 +177,6 @@ pub unsafe extern "C" fn wasmer_module_import_instantiate(
*instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t;
return wasmer_result_t::WASMER_OK; return wasmer_result_t::WASMER_OK;
*/
} }
/// Serialize the given Module. /// Serialize the given Module.
@@ -205,26 +190,18 @@ pub unsafe extern "C" fn wasmer_module_import_instantiate(
#[allow(clippy::cast_ptr_alignment)] #[allow(clippy::cast_ptr_alignment)]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasmer_module_serialize( pub unsafe extern "C" fn wasmer_module_serialize(
serialized_module: *mut *mut wasmer_serialized_module_t, serialized_module_out: *mut *mut wasmer_serialized_module_t,
module: *const wasmer_module_t, module: *const wasmer_module_t,
) -> wasmer_result_t { ) -> wasmer_result_t {
let module = &*(module as *const Module); let module = &*(module as *const Module);
/* match module.serialize() {
match module.cache() { Ok(mut serialized_module) => {
Ok(artifact) => match artifact.serialize() { let boxed_slice = serialized_module.into_boxed_slice();
Ok(serialized_artifact) => { *serialized_module_out = Box::into_raw(Box::new(boxed_slice)) as _;
*serialized_module = Box::into_raw(Box::new(serialized_artifact)) as _;
wasmer_result_t::WASMER_OK wasmer_result_t::WASMER_OK
} }
Err(_) => {
update_last_error(CApiError {
msg: "Failed to serialize the module artifact".to_string(),
});
wasmer_result_t::WASMER_ERROR
}
},
Err(_) => { Err(_) => {
update_last_error(CApiError { update_last_error(CApiError {
msg: "Failed to serialize the module".to_string(), msg: "Failed to serialize the module".to_string(),
@@ -232,8 +209,6 @@ pub unsafe extern "C" fn wasmer_module_serialize(
wasmer_result_t::WASMER_ERROR wasmer_result_t::WASMER_ERROR
} }
} }
*/
panic!("Temporarily broken in refactor");
} }
/// Get bytes of the serialized module. /// Get bytes of the serialized module.
@@ -302,28 +277,20 @@ pub unsafe extern "C" fn wasmer_module_deserialize(
} }
let serialized_module: &[u8] = &*(serialized_module as *const &[u8]); let serialized_module: &[u8] = &*(serialized_module as *const &[u8]);
let store = crate::get_global_store();
/*match Artifact::deserialize(serialized_module) { match Module::deserialize(store, serialized_module) {
Ok(artifact) => match load_cache_with(artifact, &default_compiler()) { Ok(deserialized_module) => {
Ok(deserialized_module) => { *module = Box::into_raw(Box::new(deserialized_module)) as _;
*module = Box::into_raw(Box::new(deserialized_module)) as _; wasmer_result_t::WASMER_OK
wasmer_result_t::WASMER_OK }
}
Err(_) => {
update_last_error(CApiError {
msg: "Failed to compile the serialized module".to_string(),
});
wasmer_result_t::WASMER_ERROR
}
},
Err(_) => { Err(_) => {
update_last_error(CApiError { update_last_error(CApiError {
msg: "Failed to deserialize the module".to_string(), msg: "Failed to compile the serialized module".to_string(),
}); });
wasmer_result_t::WASMER_ERROR wasmer_result_t::WASMER_ERROR
} }
}*/ }
panic!("Temporarily broken in refactor");
} }
/// Frees memory for the given serialized Module. /// Frees memory for the given serialized Module.
@@ -332,6 +299,7 @@ pub unsafe extern "C" fn wasmer_module_deserialize(
pub extern "C" fn wasmer_serialized_module_destroy( pub extern "C" fn wasmer_serialized_module_destroy(
serialized_module: *mut wasmer_serialized_module_t, serialized_module: *mut wasmer_serialized_module_t,
) { ) {
// TODO(mark): review all serialized logic memory logic
if !serialized_module.is_null() { if !serialized_module.is_null() {
unsafe { Box::from_raw(serialized_module as *mut &[u8]) }; unsafe { Box::from_raw(serialized_module as *mut &[u8]) };
} }

View File

@@ -1,12 +1,25 @@
//! Create, grow, destroy tables of an instance. //! Create, grow, destroy tables of an instance.
use crate::{error::update_last_error, wasmer_limits_t, wasmer_result_t}; use crate::{error::update_last_error, wasmer_limits_t, wasmer_result_t};
use wasmer::{Table, Val, ValType}; use wasmer::{Table, TableType, Val, ValType};
#[repr(C)] #[repr(C)]
#[derive(Clone)] #[derive(Clone)]
pub struct wasmer_table_t; pub struct wasmer_table_t;
// TODO: this logic should be in wasmer itself
fn get_default_table_value(table_type: ValType) -> Val {
match table_type {
ValType::I32 => Val::I32(0),
ValType::I64 => Val::I64(0),
ValType::F32 => Val::F32(0.),
ValType::F64 => Val::F64(0.),
ValType::V128 => Val::V128(0),
ValType::AnyRef => todo!("Figure out what the default AnyRef value is"),
ValType::FuncRef => todo!("Figure out what the default FuncRef value is"),
}
}
/// Creates a new Table for the given descriptor and initializes the given /// Creates a new Table for the given descriptor and initializes the given
/// pointer to pointer to a pointer to the new Table. /// pointer to pointer to a pointer to the new Table.
/// ///
@@ -21,18 +34,18 @@ pub unsafe extern "C" fn wasmer_table_new(
table: *mut *mut wasmer_table_t, table: *mut *mut wasmer_table_t,
limits: wasmer_limits_t, limits: wasmer_limits_t,
) -> wasmer_result_t { ) -> wasmer_result_t {
unimplemented!("wasmer_table_new needs a global store") let max = if limits.max.has_some {
/*let max = if limits.max.has_some {
Some(limits.max.some) Some(limits.max.some)
} else { } else {
None None
}; };
let desc = TableType { let desc = TableType {
ty: Type::FuncRef, ty: ValType::FuncRef,
minimum: limits.min, minimum: limits.min,
maximum: max, maximum: max,
}; };
let result = Table::new(desc); let store = crate::get_global_store();
let result = Table::new(store, desc, get_default_table_value(ValType::FuncRef));
let new_table = match result { let new_table = match result {
Ok(table) => table, Ok(table) => table,
Err(error) => { Err(error) => {
@@ -42,7 +55,6 @@ pub unsafe extern "C" fn wasmer_table_new(
}; };
*table = Box::into_raw(Box::new(new_table)) as *mut wasmer_table_t; *table = Box::into_raw(Box::new(new_table)) as *mut wasmer_table_t;
wasmer_result_t::WASMER_OK wasmer_result_t::WASMER_OK
*/
} }
/// Grows a Table by the given number of elements. /// Grows a Table by the given number of elements.
@@ -56,16 +68,7 @@ pub unsafe extern "C" fn wasmer_table_new(
pub extern "C" fn wasmer_table_grow(table: *mut wasmer_table_t, delta: u32) -> wasmer_result_t { pub extern "C" fn wasmer_table_grow(table: *mut wasmer_table_t, delta: u32) -> wasmer_result_t {
let table = unsafe { &*(table as *mut Table) }; let table = unsafe { &*(table as *mut Table) };
let table_type = table.ty().ty; let table_type = table.ty().ty;
// TODO: this logic should be in wasmer itself let table_default_value = get_default_table_value(table_type);
let table_default_value = match table_type {
ValType::I32 => Val::I32(0),
ValType::I64 => Val::I64(0),
ValType::F32 => Val::F32(0.),
ValType::F64 => Val::F64(0.),
ValType::V128 => Val::V128(0),
ValType::AnyRef => todo!("Figure out what the default AnyRef value is"),
ValType::FuncRef => todo!("Figure out what the default FuncRef value is"),
};
let delta_result = table.grow(delta, table_default_value); let delta_result = table.grow(delta, table_default_value);
match delta_result { match delta_result {
Ok(_) => wasmer_result_t::WASMER_OK, Ok(_) => wasmer_result_t::WASMER_OK,

View File

@@ -4,7 +4,8 @@ project (WasmerRuntimeCApiTests)
add_executable(test-exported-memory test-exported-memory.c) add_executable(test-exported-memory test-exported-memory.c)
add_executable(test-exports test-exports.c) add_executable(test-exports test-exports.c)
add_executable(test-globals test-globals.c) add_executable(test-globals test-globals.c)
add_executable(test-import-function test-import-function.c) # functionality not yet implemented in wasmer reborn
#add_executable(test-import-function test-import-function.c)
add_executable(test-import-trap test-import-trap.c) add_executable(test-import-trap test-import-trap.c)
add_executable(test-imports test-imports.c) add_executable(test-imports test-imports.c)
add_executable(test-import-object test-import-object.c) add_executable(test-import-object test-import-object.c)
@@ -70,9 +71,10 @@ target_link_libraries(test-globals general ${WASMER_LIB})
target_compile_options(test-globals PRIVATE ${COMPILER_OPTIONS}) target_compile_options(test-globals PRIVATE ${COMPILER_OPTIONS})
add_test(test-globals test-globals) add_test(test-globals test-globals)
target_link_libraries(test-import-function general ${WASMER_LIB}) # functionality not yet implemented in wasmer reborn
target_compile_options(test-import-function PRIVATE ${COMPILER_OPTIONS}) #target_link_libraries(test-import-function general ${WASMER_LIB})
add_test(test-import-function test-import-function) #target_compile_options(test-import-function PRIVATE ${COMPILER_OPTIONS})
#add_test(test-import-function test-import-function)
target_link_libraries(test-import-trap general ${WASMER_LIB}) target_link_libraries(test-import-trap general ${WASMER_LIB})
target_compile_options(test-import-trap PRIVATE ${COMPILER_OPTIONS}) target_compile_options(test-import-trap PRIVATE ${COMPILER_OPTIONS})

View File

@@ -1313,7 +1313,7 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module,
* Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
* and `wasmer_last_error_message` to get an error message. * and `wasmer_last_error_message` to get an error message.
*/ */
wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module, wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module_out,
const wasmer_module_t *module); const wasmer_module_t *module);
/** /**

View File

@@ -1088,7 +1088,7 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module,
/// ///
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
/// and `wasmer_last_error_message` to get an error message. /// and `wasmer_last_error_message` to get an error message.
wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module, wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module_out,
const wasmer_module_t *module); const wasmer_module_t *module);
/// Get bytes of the serialized module. /// Get bytes of the serialized module.