Refactor and fill out wasmtime's C API (#1415)
* Refactor and improve safety of C API This commit is intended to be a relatively large refactoring of the C API which is targeted at improving the safety of our C API definitions. Not all of the APIs have been updated yet but this is intended to be the start. The goal here is to make as many functions safe as we can, expressing inputs/outputs as native Rust types rather than raw pointers wherever possible. For example instead of `*const wasm_foo_t` we'd take `&wasm_foo_t`. Instead of returning `*mut wasm_foo_t` we'd return `Box<wasm_foo_t>`. No ABI/API changes are intended from this commit, it's supposed to only change how we define all these functions internally. This commit also additionally implements a few more API bindings for exposed vector types by unifying everything into one macro. Finally, this commit moves many internal caches in the C API to the `OnceCell` type which provides a safe interface for one-time initialization. * Split apart monolithic C API `lib.rs` This commit splits the monolithic `src/lib.rs` in the C API crate into lots of smaller files. The goal here is to make this a bit more readable and digestable. Each module now contains only API bindings for a particular type, roughly organized around the grouping in the wasm.h header file already. A few more extensions were added, such as filling out `*_as_*` conversions with both const and non-const versions. Additionally many APIs were made safer in the same style as the previous commit, generally preferring Rust types rather than raw pointer types. Overall no functional change is intended here, it should be mostly just code movement and minor refactorings! * Make a few wasi C bindings safer Use safe Rust types where we can and touch up a few APIs here and there. * Implement `wasm_*type_as_externtype*` APIs This commit restructures `wasm_externtype_t` to be similar to `wasm_extern_t` so type conversion between the `*_extern_*` variants to the concrete variants are all simple casts. (checked in the case of general to concrete, of course). * Consistently imlpement host info functions in the API This commit adds a small macro crate which is then used to consistently define the various host-info-related functions in the C API. The goal here is to try to mirror what the `wasm.h` header provides to provide a full implementation of the header.
This commit is contained in:
16
Cargo.lock
generated
16
Cargo.lock
generated
@@ -1308,6 +1308,12 @@ dependencies = [
|
||||
"wasmparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
@@ -2295,12 +2301,22 @@ name = "wasmtime-c-api"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"once_cell",
|
||||
"wasi-common",
|
||||
"wasmtime",
|
||||
"wasmtime-c-api-macros",
|
||||
"wasmtime-wasi",
|
||||
"wat",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-c-api-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-cli"
|
||||
version = "0.14.0"
|
||||
|
||||
@@ -29,7 +29,7 @@ pub use crate::func::*;
|
||||
pub use crate::instance::Instance;
|
||||
pub use crate::linker::*;
|
||||
pub use crate::module::Module;
|
||||
pub use crate::r#ref::{AnyRef, HostInfo, HostRef};
|
||||
pub use crate::r#ref::{AnyRef, HostRef};
|
||||
pub use crate::runtime::*;
|
||||
pub use crate::trap::Trap;
|
||||
pub use crate::types::*;
|
||||
|
||||
@@ -5,14 +5,10 @@ use std::cell::{self, RefCell};
|
||||
use std::fmt;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
||||
pub trait HostInfo {
|
||||
fn finalize(&mut self) {}
|
||||
}
|
||||
|
||||
trait InternalRefBase: Any {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn host_info(&self) -> Option<cell::RefMut<Box<dyn HostInfo>>>;
|
||||
fn set_host_info(&self, info: Option<Box<dyn HostInfo>>);
|
||||
fn host_info(&self) -> Option<cell::RefMut<Box<dyn Any>>>;
|
||||
fn set_host_info(&self, info: Option<Box<dyn Any>>);
|
||||
fn ptr_eq(&self, other: &dyn InternalRefBase) -> bool;
|
||||
}
|
||||
|
||||
@@ -34,15 +30,7 @@ impl InternalRef {
|
||||
|
||||
struct AnyAndHostInfo {
|
||||
any: Box<dyn Any>,
|
||||
host_info: Option<Box<dyn HostInfo>>,
|
||||
}
|
||||
|
||||
impl Drop for AnyAndHostInfo {
|
||||
fn drop(&mut self) {
|
||||
if let Some(info) = &mut self.host_info {
|
||||
info.finalize();
|
||||
}
|
||||
}
|
||||
host_info: Option<Box<dyn Any>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -100,7 +88,7 @@ impl AnyRef {
|
||||
/// Returns a mutable reference to the host information if available.
|
||||
/// # Panics
|
||||
/// Panics if `AnyRef` is already borrowed or `AnyRef` is `Null`.
|
||||
pub fn host_info(&self) -> Option<cell::RefMut<Box<dyn HostInfo>>> {
|
||||
pub fn host_info(&self) -> Option<cell::RefMut<Box<dyn Any>>> {
|
||||
match self {
|
||||
AnyRef::Null => panic!("null"),
|
||||
AnyRef::Ref(r) => r.0.host_info(),
|
||||
@@ -117,7 +105,7 @@ impl AnyRef {
|
||||
/// Sets the host information for an `AnyRef`.
|
||||
/// # Panics
|
||||
/// Panics if `AnyRef` is already borrowed or `AnyRef` is `Null`.
|
||||
pub fn set_host_info(&self, info: Option<Box<dyn HostInfo>>) {
|
||||
pub fn set_host_info(&self, info: Option<Box<dyn Any>>) {
|
||||
match self {
|
||||
AnyRef::Null => panic!("null"),
|
||||
AnyRef::Ref(r) => r.0.set_host_info(info),
|
||||
@@ -140,18 +128,10 @@ impl fmt::Debug for AnyRef {
|
||||
|
||||
struct ContentBox<T> {
|
||||
content: T,
|
||||
host_info: Option<Box<dyn HostInfo>>,
|
||||
host_info: Option<Box<dyn Any>>,
|
||||
anyref_data: Weak<dyn InternalRefBase>,
|
||||
}
|
||||
|
||||
impl<T> Drop for ContentBox<T> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(info) = &mut self.host_info {
|
||||
info.finalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a piece of data located in the host environment.
|
||||
pub struct HostRef<T>(Rc<RefCell<ContentBox<T>>>);
|
||||
|
||||
@@ -215,7 +195,7 @@ impl<T: 'static> InternalRefBase for HostRef<T> {
|
||||
self
|
||||
}
|
||||
|
||||
fn host_info(&self) -> Option<cell::RefMut<Box<dyn HostInfo>>> {
|
||||
fn host_info(&self) -> Option<cell::RefMut<Box<dyn Any>>> {
|
||||
let info = cell::RefMut::map(self.0.borrow_mut(), |b| &mut b.host_info);
|
||||
if info.is_none() {
|
||||
return None;
|
||||
@@ -223,7 +203,7 @@ impl<T: 'static> InternalRefBase for HostRef<T> {
|
||||
Some(cell::RefMut::map(info, |info| info.as_mut().unwrap()))
|
||||
}
|
||||
|
||||
fn set_host_info(&self, info: Option<Box<dyn HostInfo>>) {
|
||||
fn set_host_info(&self, info: Option<Box<dyn Any>>) {
|
||||
self.0.borrow_mut().host_info = info;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +159,30 @@ impl ExternType {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FuncType> for ExternType {
|
||||
fn from(ty: FuncType) -> ExternType {
|
||||
ExternType::Func(ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GlobalType> for ExternType {
|
||||
fn from(ty: GlobalType) -> ExternType {
|
||||
ExternType::Global(ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MemoryType> for ExternType {
|
||||
fn from(ty: MemoryType) -> ExternType {
|
||||
ExternType::Memory(ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TableType> for ExternType {
|
||||
fn from(ty: TableType) -> ExternType {
|
||||
ExternType::Table(ty)
|
||||
}
|
||||
}
|
||||
|
||||
// Function Types
|
||||
fn from_wasmtime_abiparam(param: &ir::AbiParam) -> Option<ValType> {
|
||||
assert_eq!(param.purpose, ir::ArgumentPurpose::Normal);
|
||||
|
||||
@@ -18,9 +18,11 @@ doctest = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
once_cell = "1.3"
|
||||
wasmtime = { path = "../api", default-features = false }
|
||||
wasi-common = { path = "../wasi-common" }
|
||||
wasmtime-wasi = { path = "../wasi" }
|
||||
wasmtime-c-api-macros = { path = "macros" }
|
||||
wat = "1.0"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -32,19 +32,19 @@ enum wasmtime_profiling_strategy_t { // ProfilingStrategy
|
||||
WASMTIME_PROFILING_STRATEGY_JITDUMP,
|
||||
};
|
||||
|
||||
#define WASMTIME_CONFIG_PROP(name, ty) \
|
||||
WASM_API_EXTERN void wasmtime_config_##name##_set(wasm_config_t*, ty);
|
||||
#define WASMTIME_CONFIG_PROP(ret, name, ty) \
|
||||
WASM_API_EXTERN ret wasmtime_config_##name##_set(wasm_config_t*, ty);
|
||||
|
||||
WASMTIME_CONFIG_PROP(debug_info, bool)
|
||||
WASMTIME_CONFIG_PROP(wasm_threads, bool)
|
||||
WASMTIME_CONFIG_PROP(wasm_reference_types, bool)
|
||||
WASMTIME_CONFIG_PROP(wasm_simd, bool)
|
||||
WASMTIME_CONFIG_PROP(wasm_bulk_memory, bool)
|
||||
WASMTIME_CONFIG_PROP(wasm_multi_value, bool)
|
||||
WASMTIME_CONFIG_PROP(strategy, wasmtime_strategy_t)
|
||||
WASMTIME_CONFIG_PROP(cranelift_debug_verifier, bool)
|
||||
WASMTIME_CONFIG_PROP(cranelift_opt_level, wasmtime_opt_level_t)
|
||||
WASMTIME_CONFIG_PROP(profiler, wasmtime_profiling_strategy_t)
|
||||
WASMTIME_CONFIG_PROP(void, debug_info, bool)
|
||||
WASMTIME_CONFIG_PROP(void, wasm_threads, bool)
|
||||
WASMTIME_CONFIG_PROP(void, wasm_reference_types, bool)
|
||||
WASMTIME_CONFIG_PROP(void, wasm_simd, bool)
|
||||
WASMTIME_CONFIG_PROP(void, wasm_bulk_memory, bool)
|
||||
WASMTIME_CONFIG_PROP(void, wasm_multi_value, bool)
|
||||
WASMTIME_CONFIG_PROP(bool, strategy, wasmtime_strategy_t)
|
||||
WASMTIME_CONFIG_PROP(void, cranelift_debug_verifier, bool)
|
||||
WASMTIME_CONFIG_PROP(void, cranelift_opt_level, wasmtime_opt_level_t)
|
||||
WASMTIME_CONFIG_PROP(bool, profiler, wasmtime_profiling_strategy_t)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
13
crates/c-api/macros/Cargo.toml
Normal file
13
crates/c-api/macros/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "wasmtime-c-api-macros"
|
||||
version = "0.1.0"
|
||||
authors = ["The Wasmtime Project Developers"]
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
112
crates/c-api/macros/src/lib.rs
Normal file
112
crates/c-api/macros/src/lib.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
//! A set of convenience macros for our wasmtime-c-api crate.
|
||||
//!
|
||||
//! These are intended to mirror the macros in the `wasm.h` header file and
|
||||
//! largely facilitate the `declare_ref` macro.
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
use proc_macro2::{Ident, TokenStream, TokenTree};
|
||||
use quote::quote;
|
||||
|
||||
fn extract_ident(input: proc_macro::TokenStream) -> Ident {
|
||||
let input = TokenStream::from(input);
|
||||
let i = match input.into_iter().next().unwrap() {
|
||||
TokenTree::Ident(i) => i,
|
||||
_ => panic!("expected an ident"),
|
||||
};
|
||||
let name = i.to_string();
|
||||
assert!(name.ends_with("_t"));
|
||||
return i;
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn declare_own(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let ty = extract_ident(input);
|
||||
let name = ty.to_string();
|
||||
let delete = quote::format_ident!("{}_delete", &name[..name.len() - 2]);
|
||||
|
||||
(quote! {
|
||||
#[no_mangle]
|
||||
pub extern fn #delete(_: Box<#ty>) {}
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn declare_ty(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let ty = extract_ident(input);
|
||||
let name = ty.to_string();
|
||||
let copy = quote::format_ident!("{}_copy", &name[..name.len() - 2]);
|
||||
|
||||
(quote! {
|
||||
wasmtime_c_api_macros::declare_own!(#ty);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn #copy(src: &#ty) -> Box<#ty> {
|
||||
Box::new(src.clone())
|
||||
}
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let ty = extract_ident(input);
|
||||
let name = ty.to_string();
|
||||
let prefix = &name[..name.len() - 2];
|
||||
let copy = quote::format_ident!("{}_copy", prefix);
|
||||
let same = quote::format_ident!("{}_same", prefix);
|
||||
let get_host_info = quote::format_ident!("{}_get_host_info", prefix);
|
||||
let set_host_info = quote::format_ident!("{}_set_host_info", prefix);
|
||||
let set_host_info_final = quote::format_ident!("{}_set_host_info_with_finalizer", prefix);
|
||||
let as_ref = quote::format_ident!("{}_as_ref", prefix);
|
||||
let as_ref_const = quote::format_ident!("{}_as_ref_const", prefix);
|
||||
|
||||
(quote! {
|
||||
wasmtime_c_api_macros::declare_own!(#ty);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn #copy(src: &#ty) -> Box<#ty> {
|
||||
Box::new(src.clone())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn #same(a: &#ty, b: &#ty) -> bool {
|
||||
a.anyref().ptr_eq(&b.anyref())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn #get_host_info(a: &#ty) -> *mut std::os::raw::c_void {
|
||||
crate::r#ref::get_host_info(&a.anyref())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn #set_host_info(a: &#ty, info: *mut std::os::raw::c_void) {
|
||||
crate::r#ref::set_host_info(&a.anyref(), info, None)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn #set_host_info_final(
|
||||
a: &#ty,
|
||||
info: *mut std::os::raw::c_void,
|
||||
finalizer: Option<extern "C" fn(*mut std::os::raw::c_void)>,
|
||||
) {
|
||||
crate::r#ref::set_host_info(&a.anyref(), info, finalizer)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn #as_ref(a: &#ty) -> Box<crate::wasm_ref_t> {
|
||||
let r = a.anyref();
|
||||
Box::new(crate::wasm_ref_t { r })
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn #as_ref_const(a: &#ty) -> Box<crate::wasm_ref_t> {
|
||||
#as_ref(a)
|
||||
}
|
||||
|
||||
// TODO: implement `wasm_ref_as_#name#`
|
||||
// TODO: implement `wasm_ref_as_#name#_const`
|
||||
})
|
||||
.into()
|
||||
}
|
||||
119
crates/c-api/src/config.rs
Normal file
119
crates/c-api/src/config.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
use wasmtime::{Config, OptLevel, ProfilingStrategy, Strategy};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_config_t {
|
||||
pub(crate) config: Config,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_own!(wasm_config_t);
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone)]
|
||||
pub enum wasmtime_strategy_t {
|
||||
WASMTIME_STRATEGY_AUTO,
|
||||
WASMTIME_STRATEGY_CRANELIFT,
|
||||
WASMTIME_STRATEGY_LIGHTBEAM,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone)]
|
||||
pub enum wasmtime_opt_level_t {
|
||||
WASMTIME_OPT_LEVEL_NONE,
|
||||
WASMTIME_OPT_LEVEL_SPEED,
|
||||
WASMTIME_OPT_LEVEL_SPEED_AND_SIZE,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone)]
|
||||
pub enum wasmtime_profiling_strategy_t {
|
||||
WASMTIME_PROFILING_STRATEGY_NONE,
|
||||
WASMTIME_PROFILING_STRATEGY_JITDUMP,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_config_new() -> Box<wasm_config_t> {
|
||||
Box::new(wasm_config_t {
|
||||
config: Config::default(),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_debug_info_set(c: &mut wasm_config_t, enable: bool) {
|
||||
c.config.debug_info(enable);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_wasm_threads_set(c: &mut wasm_config_t, enable: bool) {
|
||||
c.config.wasm_threads(enable);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_wasm_reference_types_set(c: &mut wasm_config_t, enable: bool) {
|
||||
c.config.wasm_reference_types(enable);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_wasm_simd_set(c: &mut wasm_config_t, enable: bool) {
|
||||
c.config.wasm_simd(enable);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_wasm_bulk_memory_set(c: &mut wasm_config_t, enable: bool) {
|
||||
c.config.wasm_bulk_memory(enable);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_wasm_multi_value_set(c: &mut wasm_config_t, enable: bool) {
|
||||
c.config.wasm_multi_value(enable);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_strategy_set(
|
||||
c: &mut wasm_config_t,
|
||||
strategy: wasmtime_strategy_t,
|
||||
) -> bool {
|
||||
use wasmtime_strategy_t::*;
|
||||
c.config
|
||||
.strategy(match strategy {
|
||||
WASMTIME_STRATEGY_AUTO => Strategy::Auto,
|
||||
WASMTIME_STRATEGY_CRANELIFT => Strategy::Cranelift,
|
||||
WASMTIME_STRATEGY_LIGHTBEAM => Strategy::Lightbeam,
|
||||
})
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_cranelift_debug_verifier_set(
|
||||
c: &mut wasm_config_t,
|
||||
enable: bool,
|
||||
) {
|
||||
c.config.cranelift_debug_verifier(enable);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_cranelift_opt_level_set(
|
||||
c: &mut wasm_config_t,
|
||||
opt_level: wasmtime_opt_level_t,
|
||||
) {
|
||||
use wasmtime_opt_level_t::*;
|
||||
c.config.cranelift_opt_level(match opt_level {
|
||||
WASMTIME_OPT_LEVEL_NONE => OptLevel::None,
|
||||
WASMTIME_OPT_LEVEL_SPEED => OptLevel::Speed,
|
||||
WASMTIME_OPT_LEVEL_SPEED_AND_SIZE => OptLevel::SpeedAndSize,
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_config_profiler_set(
|
||||
c: &mut wasm_config_t,
|
||||
strategy: wasmtime_profiling_strategy_t,
|
||||
) -> bool {
|
||||
use wasmtime_profiling_strategy_t::*;
|
||||
c.config
|
||||
.profiler(match strategy {
|
||||
WASMTIME_PROFILING_STRATEGY_NONE => ProfilingStrategy::None,
|
||||
WASMTIME_PROFILING_STRATEGY_JITDUMP => ProfilingStrategy::JitDump,
|
||||
})
|
||||
.is_ok()
|
||||
}
|
||||
25
crates/c-api/src/engine.rs
Normal file
25
crates/c-api/src/engine.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use crate::wasm_config_t;
|
||||
use wasmtime::{Engine, HostRef};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_engine_t {
|
||||
pub(crate) engine: HostRef<Engine>,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_own!(wasm_engine_t);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> {
|
||||
Box::new(wasm_engine_t {
|
||||
engine: HostRef::new(Engine::default()),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_engine_new_with_config(c: Box<wasm_config_t>) -> Box<wasm_engine_t> {
|
||||
let config = c.config;
|
||||
Box::new(wasm_engine_t {
|
||||
engine: HostRef::new(Engine::new(&config)),
|
||||
})
|
||||
}
|
||||
@@ -108,28 +108,28 @@ pub unsafe extern "C" fn wasmtime_config_profiler_set(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_wat2wasm(
|
||||
wat: *const wasm_byte_vec_t,
|
||||
ret: *mut wasm_byte_vec_t,
|
||||
error: *mut wasm_byte_vec_t,
|
||||
pub extern "C" fn wasmtime_wat2wasm(
|
||||
wat: &wasm_byte_vec_t,
|
||||
ret: &mut wasm_byte_vec_t,
|
||||
error: Option<&mut wasm_byte_vec_t>,
|
||||
) -> bool {
|
||||
let wat = match str::from_utf8((*wat).as_slice()) {
|
||||
let wat = match str::from_utf8(wat.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => {
|
||||
if !error.is_null() {
|
||||
(*error).set_from_slice(b"input was not valid utf-8");
|
||||
if let Some(error) = error {
|
||||
error.set_buffer(b"input was not valid utf-8".to_vec());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
match wat::parse_str(wat) {
|
||||
Ok(bytes) => {
|
||||
(*ret).set_from_slice(&bytes);
|
||||
ret.set_buffer(bytes.into());
|
||||
true
|
||||
}
|
||||
Err(e) => {
|
||||
if !error.is_null() {
|
||||
(*error).set_from_slice(e.to_string().as_bytes());
|
||||
if let Some(error) = error {
|
||||
error.set_buffer(e.to_string().into_bytes());
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
90
crates/c-api/src/extern.rs
Normal file
90
crates/c-api/src/extern.rs
Normal file
@@ -0,0 +1,90 @@
|
||||
use crate::wasm_externkind_t;
|
||||
use crate::{wasm_externtype_t, wasm_func_t, wasm_global_t, wasm_memory_t, wasm_table_t};
|
||||
use wasmtime::{ExternType, Func, Global, HostRef, Memory, Table};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_extern_t {
|
||||
pub(crate) which: ExternHost,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_extern_t);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum ExternHost {
|
||||
Func(HostRef<Func>),
|
||||
Global(HostRef<Global>),
|
||||
Memory(HostRef<Memory>),
|
||||
Table(HostRef<Table>),
|
||||
}
|
||||
|
||||
impl wasm_extern_t {
|
||||
fn anyref(&self) -> wasmtime::AnyRef {
|
||||
match &self.which {
|
||||
ExternHost::Func(f) => f.anyref(),
|
||||
ExternHost::Global(f) => f.anyref(),
|
||||
ExternHost::Memory(f) => f.anyref(),
|
||||
ExternHost::Table(f) => f.anyref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t {
|
||||
match e.which {
|
||||
ExternHost::Func(_) => crate::WASM_EXTERN_FUNC,
|
||||
ExternHost::Global(_) => crate::WASM_EXTERN_GLOBAL,
|
||||
ExternHost::Table(_) => crate::WASM_EXTERN_TABLE,
|
||||
ExternHost::Memory(_) => crate::WASM_EXTERN_MEMORY,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box<wasm_externtype_t> {
|
||||
let ty = match &e.which {
|
||||
ExternHost::Func(f) => ExternType::Func(f.borrow().ty().clone()),
|
||||
ExternHost::Global(f) => ExternType::Global(f.borrow().ty().clone()),
|
||||
ExternHost::Table(f) => ExternType::Table(f.borrow().ty().clone()),
|
||||
ExternHost::Memory(f) => ExternType::Memory(f.borrow().ty().clone()),
|
||||
};
|
||||
Box::new(wasm_externtype_t::new(ty))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_as_func(e: &wasm_extern_t) -> Option<&wasm_func_t> {
|
||||
wasm_func_t::try_from(e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_as_func_const(e: &wasm_extern_t) -> Option<&wasm_func_t> {
|
||||
wasm_extern_as_func(e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_as_global(e: &wasm_extern_t) -> Option<&wasm_global_t> {
|
||||
wasm_global_t::try_from(e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_as_global_const(e: &wasm_extern_t) -> Option<&wasm_global_t> {
|
||||
wasm_extern_as_global(e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_as_table(e: &wasm_extern_t) -> Option<&wasm_table_t> {
|
||||
wasm_table_t::try_from(e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_as_table_const(e: &wasm_extern_t) -> Option<&wasm_table_t> {
|
||||
wasm_extern_as_table(e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_as_memory(e: &wasm_extern_t) -> Option<&wasm_memory_t> {
|
||||
wasm_memory_t::try_from(e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_extern_as_memory_const(e: &wasm_extern_t) -> Option<&wasm_memory_t> {
|
||||
wasm_extern_as_memory(e)
|
||||
}
|
||||
243
crates/c-api/src/func.rs
Normal file
243
crates/c-api/src/func.rs
Normal file
@@ -0,0 +1,243 @@
|
||||
use crate::{wasm_extern_t, wasm_functype_t, wasm_store_t, wasm_val_t};
|
||||
use crate::{wasm_name_t, wasm_trap_t, ExternHost};
|
||||
use std::ffi::c_void;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
use wasmtime::{Caller, Extern, Func, HostRef, Trap};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_func_t {
|
||||
ext: wasm_extern_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_func_t);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmtime_caller_t<'a> {
|
||||
caller: Caller<'a>,
|
||||
}
|
||||
|
||||
pub type wasm_func_callback_t =
|
||||
extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> Option<Box<wasm_trap_t>>;
|
||||
|
||||
pub type wasm_func_callback_with_env_t = extern "C" fn(
|
||||
env: *mut std::ffi::c_void,
|
||||
args: *const wasm_val_t,
|
||||
results: *mut wasm_val_t,
|
||||
) -> Option<Box<wasm_trap_t>>;
|
||||
|
||||
pub type wasmtime_func_callback_t = extern "C" fn(
|
||||
caller: *const wasmtime_caller_t,
|
||||
args: *const wasm_val_t,
|
||||
results: *mut wasm_val_t,
|
||||
) -> Option<Box<wasm_trap_t>>;
|
||||
|
||||
pub type wasmtime_func_callback_with_env_t = extern "C" fn(
|
||||
caller: *const wasmtime_caller_t,
|
||||
env: *mut std::ffi::c_void,
|
||||
args: *const wasm_val_t,
|
||||
results: *mut wasm_val_t,
|
||||
) -> Option<Box<wasm_trap_t>>;
|
||||
|
||||
struct Finalizer {
|
||||
env: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
}
|
||||
|
||||
impl Drop for Finalizer {
|
||||
fn drop(&mut self) {
|
||||
if let Some(f) = self.finalizer {
|
||||
f(self.env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl wasm_func_t {
|
||||
pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_func_t> {
|
||||
match &e.which {
|
||||
ExternHost::Func(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn func(&self) -> &HostRef<Func> {
|
||||
match &self.ext.which {
|
||||
ExternHost::Func(f) => f,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
|
||||
fn anyref(&self) -> wasmtime::AnyRef {
|
||||
self.func().anyref()
|
||||
}
|
||||
}
|
||||
|
||||
fn create_function(
|
||||
store: &wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
func: impl Fn(Caller<'_>, *const wasm_val_t, *mut wasm_val_t) -> Option<Box<wasm_trap_t>> + 'static,
|
||||
) -> Box<wasm_func_t> {
|
||||
let store = &store.store.borrow();
|
||||
let ty = ty.ty().ty.clone();
|
||||
let func = Func::new(store, ty, move |caller, params, results| {
|
||||
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 out = func(caller, params.as_ptr(), out_results.as_mut_ptr());
|
||||
if let Some(trap) = out {
|
||||
return Err(trap.trap.borrow().clone());
|
||||
}
|
||||
for i in 0..results.len() {
|
||||
results[i] = out_results[i].val();
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
Box::new(wasm_func_t {
|
||||
ext: wasm_extern_t {
|
||||
which: ExternHost::Func(HostRef::new(func)),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_new(
|
||||
store: &wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
callback: wasm_func_callback_t,
|
||||
) -> Box<wasm_func_t> {
|
||||
create_function(store, ty, move |_caller, params, results| {
|
||||
callback(params, results)
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_func_new(
|
||||
store: &wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
callback: wasmtime_func_callback_t,
|
||||
) -> Box<wasm_func_t> {
|
||||
create_function(store, ty, move |caller, params, results| {
|
||||
callback(&wasmtime_caller_t { caller }, params, results)
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_new_with_env(
|
||||
store: &wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
callback: wasm_func_callback_with_env_t,
|
||||
env: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(arg1: *mut std::ffi::c_void)>,
|
||||
) -> Box<wasm_func_t> {
|
||||
let finalizer = Finalizer { env, finalizer };
|
||||
create_function(store, ty, move |_caller, params, results| {
|
||||
callback(finalizer.env, params, results)
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_func_new_with_env(
|
||||
store: &wasm_store_t,
|
||||
ty: &wasm_functype_t,
|
||||
callback: wasmtime_func_callback_with_env_t,
|
||||
env: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
) -> Box<wasm_func_t> {
|
||||
let finalizer = Finalizer { env, finalizer };
|
||||
create_function(store, ty, move |caller, params, results| {
|
||||
callback(
|
||||
&wasmtime_caller_t { caller },
|
||||
finalizer.env,
|
||||
params,
|
||||
results,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_func_call(
|
||||
func: &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.add(i));
|
||||
params.push(val.val());
|
||||
}
|
||||
|
||||
// We're calling arbitrary code here most of the time, and we in general
|
||||
// want to try to insulate callers against bugs in wasmtime/wasi/etc if we
|
||||
// can. As a result we catch panics here and transform them to traps to
|
||||
// allow the caller to have any insulation possible against Rust panics.
|
||||
let result = panic::catch_unwind(AssertUnwindSafe(|| func.call(¶ms)));
|
||||
match result {
|
||||
Ok(Ok(out)) => {
|
||||
for i in 0..func.result_arity() {
|
||||
let val = &mut (*results.add(i));
|
||||
*val = wasm_val_t::from_val(&out[i]);
|
||||
}
|
||||
ptr::null_mut()
|
||||
}
|
||||
Ok(Err(trap)) => {
|
||||
let trap = Box::new(wasm_trap_t {
|
||||
trap: HostRef::new(trap),
|
||||
});
|
||||
Box::into_raw(trap)
|
||||
}
|
||||
Err(panic) => {
|
||||
let trap = if let Some(msg) = panic.downcast_ref::<String>() {
|
||||
Trap::new(msg)
|
||||
} else if let Some(msg) = panic.downcast_ref::<&'static str>() {
|
||||
Trap::new(*msg)
|
||||
} else {
|
||||
Trap::new("rust panic happened")
|
||||
};
|
||||
let trap = Box::new(wasm_trap_t {
|
||||
trap: HostRef::new(trap),
|
||||
});
|
||||
Box::into_raw(trap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_type(f: &wasm_func_t) -> Box<wasm_functype_t> {
|
||||
Box::new(wasm_functype_t::new(f.func().borrow().ty().clone()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_param_arity(f: &wasm_func_t) -> usize {
|
||||
f.func().borrow().param_arity()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_result_arity(f: &wasm_func_t) -> usize {
|
||||
f.func().borrow().result_arity()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_func_as_extern(f: &mut wasm_func_t) -> &mut wasm_extern_t {
|
||||
&mut (*f).ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_caller_export_get(
|
||||
caller: &wasmtime_caller_t,
|
||||
name: &wasm_name_t,
|
||||
) -> Option<Box<wasm_extern_t>> {
|
||||
let name = str::from_utf8(name.as_slice()).ok()?;
|
||||
let export = caller.caller.get_export(name)?;
|
||||
let which = match export {
|
||||
Extern::Func(f) => ExternHost::Func(HostRef::new(f.clone())),
|
||||
Extern::Global(g) => ExternHost::Global(HostRef::new(g.clone())),
|
||||
Extern::Memory(m) => ExternHost::Memory(HostRef::new(m.clone())),
|
||||
Extern::Table(t) => ExternHost::Table(HostRef::new(t.clone())),
|
||||
};
|
||||
Some(Box::new(wasm_extern_t { which }))
|
||||
}
|
||||
68
crates/c-api/src/global.rs
Normal file
68
crates/c-api/src/global.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use crate::{wasm_extern_t, wasm_globaltype_t, wasm_store_t, wasm_val_t, ExternHost};
|
||||
use wasmtime::{Global, HostRef};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_global_t {
|
||||
ext: wasm_extern_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_global_t);
|
||||
|
||||
impl wasm_global_t {
|
||||
pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_global_t> {
|
||||
match &e.which {
|
||||
ExternHost::Global(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn global(&self) -> &HostRef<Global> {
|
||||
match &self.ext.which {
|
||||
ExternHost::Global(g) => g,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
|
||||
fn anyref(&self) -> wasmtime::AnyRef {
|
||||
self.global().anyref()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_new(
|
||||
store: &wasm_store_t,
|
||||
gt: &wasm_globaltype_t,
|
||||
val: &wasm_val_t,
|
||||
) -> Option<Box<wasm_global_t>> {
|
||||
let global =
|
||||
HostRef::new(Global::new(&store.store.borrow(), gt.ty().ty.clone(), val.val()).ok()?);
|
||||
Some(Box::new(wasm_global_t {
|
||||
ext: wasm_extern_t {
|
||||
which: ExternHost::Global(global),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_as_extern(g: &wasm_global_t) -> &wasm_extern_t {
|
||||
&g.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_type(g: &wasm_global_t) -> Box<wasm_globaltype_t> {
|
||||
let globaltype = g.global().borrow().ty().clone();
|
||||
Box::new(wasm_globaltype_t::new(globaltype))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_get(g: &wasm_global_t, out: &mut wasm_val_t) {
|
||||
out.set(g.global().borrow().get());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_global_set(g: &wasm_global_t, val: &wasm_val_t) {
|
||||
let result = g.global().borrow().set(val.val());
|
||||
// FIXME(WebAssembly/wasm-c-api#131) should communicate the error here
|
||||
drop(result);
|
||||
}
|
||||
111
crates/c-api/src/instance.rs
Normal file
111
crates/c-api/src/instance.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t};
|
||||
use crate::{wasm_store_t, ExternHost};
|
||||
use anyhow::Result;
|
||||
use std::cell::RefCell;
|
||||
use std::ptr;
|
||||
use wasmtime::{Extern, HostRef, Instance, Store, Trap};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_instance_t {
|
||||
pub(crate) instance: HostRef<Instance>,
|
||||
exports_cache: RefCell<Option<Vec<ExternHost>>>,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_instance_t);
|
||||
|
||||
impl wasm_instance_t {
|
||||
fn new(instance: Instance) -> wasm_instance_t {
|
||||
wasm_instance_t {
|
||||
instance: HostRef::new(instance),
|
||||
exports_cache: RefCell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn anyref(&self) -> wasmtime::AnyRef {
|
||||
self.instance.anyref()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_instance_new(
|
||||
store: &wasm_store_t,
|
||||
module: &wasm_module_t,
|
||||
imports: *const Box<wasm_extern_t>,
|
||||
result: Option<&mut *mut wasm_trap_t>,
|
||||
) -> Option<Box<wasm_instance_t>> {
|
||||
let mut externs: Vec<Extern> = Vec::with_capacity((*module).imports.len());
|
||||
for i in 0..(*module).imports.len() {
|
||||
let import = &*imports.add(i);
|
||||
externs.push(match &import.which {
|
||||
ExternHost::Func(e) => Extern::Func(e.borrow().clone()),
|
||||
ExternHost::Table(e) => Extern::Table(e.borrow().clone()),
|
||||
ExternHost::Global(e) => Extern::Global(e.borrow().clone()),
|
||||
ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()),
|
||||
});
|
||||
}
|
||||
let store = &(*store).store.borrow();
|
||||
let module = &(*module).module.borrow();
|
||||
if !Store::same(&store, module.store()) {
|
||||
if let Some(result) = result {
|
||||
let trap = Trap::new("wasm_store_t must match store in wasm_module_t");
|
||||
let trap = Box::new(wasm_trap_t {
|
||||
trap: HostRef::new(trap),
|
||||
});
|
||||
*result = Box::into_raw(trap);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
handle_instantiate(Instance::new(module, &externs), result)
|
||||
}
|
||||
|
||||
pub fn handle_instantiate(
|
||||
instance: Result<Instance>,
|
||||
result: Option<&mut *mut wasm_trap_t>,
|
||||
) -> Option<Box<wasm_instance_t>> {
|
||||
match instance {
|
||||
Ok(instance) => {
|
||||
if let Some(result) = result {
|
||||
*result = ptr::null_mut();
|
||||
}
|
||||
Some(Box::new(wasm_instance_t::new(instance)))
|
||||
}
|
||||
Err(trap) => {
|
||||
if let Some(result) = result {
|
||||
let trap = match trap.downcast::<Trap>() {
|
||||
Ok(trap) => trap,
|
||||
Err(e) => Trap::new(format!("{:?}", e)),
|
||||
};
|
||||
let trap = Box::new(wasm_trap_t {
|
||||
trap: HostRef::new(trap),
|
||||
});
|
||||
*result = Box::into_raw(trap);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) {
|
||||
let mut cache = instance.exports_cache.borrow_mut();
|
||||
let exports = cache.get_or_insert_with(|| {
|
||||
let instance = &instance.instance.borrow();
|
||||
instance
|
||||
.exports()
|
||||
.iter()
|
||||
.map(|e| match e {
|
||||
Extern::Func(f) => ExternHost::Func(HostRef::new(f.clone())),
|
||||
Extern::Global(f) => ExternHost::Global(HostRef::new(f.clone())),
|
||||
Extern::Memory(f) => ExternHost::Memory(HostRef::new(f.clone())),
|
||||
Extern::Table(f) => ExternHost::Table(HostRef::new(f.clone())),
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
let mut buffer = Vec::with_capacity(exports.len());
|
||||
for e in exports {
|
||||
let ext = Box::new(wasm_extern_t { which: e.clone() });
|
||||
buffer.push(Some(ext));
|
||||
}
|
||||
out.set_buffer(buffer);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
86
crates/c-api/src/linker.rs
Normal file
86
crates/c-api/src/linker.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
use crate::{wasi_instance_t, wasm_extern_t, wasm_store_t, ExternHost};
|
||||
use crate::{wasm_instance_t, wasm_module_t, wasm_name_t, wasm_trap_t};
|
||||
use std::str;
|
||||
use wasmtime::{Extern, Linker};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmtime_linker_t {
|
||||
linker: Linker,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_new(store: &wasm_store_t) -> Box<wasmtime_linker_t> {
|
||||
Box::new(wasmtime_linker_t {
|
||||
linker: Linker::new(&store.store.borrow()),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_allow_shadowing(
|
||||
linker: &mut wasmtime_linker_t,
|
||||
allow_shadowing: bool,
|
||||
) {
|
||||
linker.linker.allow_shadowing(allow_shadowing);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_delete(_linker: Box<wasmtime_linker_t>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_define(
|
||||
linker: &mut wasmtime_linker_t,
|
||||
module: &wasm_name_t,
|
||||
name: &wasm_name_t,
|
||||
item: &wasm_extern_t,
|
||||
) -> bool {
|
||||
let linker = &mut linker.linker;
|
||||
let module = match str::from_utf8(module.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let name = match str::from_utf8(name.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let item = match &item.which {
|
||||
ExternHost::Func(e) => Extern::Func(e.borrow().clone()),
|
||||
ExternHost::Table(e) => Extern::Table(e.borrow().clone()),
|
||||
ExternHost::Global(e) => Extern::Global(e.borrow().clone()),
|
||||
ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()),
|
||||
};
|
||||
linker.define(module, name, item).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_define_wasi(
|
||||
linker: &mut wasmtime_linker_t,
|
||||
instance: &wasi_instance_t,
|
||||
) -> bool {
|
||||
let linker = &mut linker.linker;
|
||||
instance.add_to_linker(linker).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_linker_define_instance(
|
||||
linker: &mut wasmtime_linker_t,
|
||||
name: &wasm_name_t,
|
||||
instance: &wasm_instance_t,
|
||||
) -> bool {
|
||||
let linker = &mut linker.linker;
|
||||
let name = match str::from_utf8(name.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return false,
|
||||
};
|
||||
linker.instance(name, &instance.instance.borrow()).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_linker_instantiate(
|
||||
linker: &wasmtime_linker_t,
|
||||
module: &wasm_module_t,
|
||||
trap: Option<&mut *mut wasm_trap_t>,
|
||||
) -> Option<Box<wasm_instance_t>> {
|
||||
let linker = &linker.linker;
|
||||
let result = linker.instantiate(&module.module.borrow());
|
||||
super::instance::handle_instantiate(result, trap)
|
||||
}
|
||||
76
crates/c-api/src/memory.rs
Normal file
76
crates/c-api/src/memory.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
use crate::{wasm_extern_t, wasm_memorytype_t, wasm_store_t, ExternHost};
|
||||
use wasmtime::{HostRef, Memory};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_memory_t {
|
||||
ext: wasm_extern_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_memory_t);
|
||||
|
||||
pub type wasm_memory_pages_t = u32;
|
||||
|
||||
impl wasm_memory_t {
|
||||
pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_memory_t> {
|
||||
match &e.which {
|
||||
ExternHost::Memory(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn memory(&self) -> &HostRef<Memory> {
|
||||
match &self.ext.which {
|
||||
ExternHost::Memory(m) => m,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
|
||||
fn anyref(&self) -> wasmtime::AnyRef {
|
||||
self.memory().anyref()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_new(
|
||||
store: &wasm_store_t,
|
||||
mt: &wasm_memorytype_t,
|
||||
) -> Box<wasm_memory_t> {
|
||||
let memory = HostRef::new(Memory::new(&store.store.borrow(), mt.ty().ty.clone()));
|
||||
Box::new(wasm_memory_t {
|
||||
ext: wasm_extern_t {
|
||||
which: ExternHost::Memory(memory),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_as_extern(m: &wasm_memory_t) -> &wasm_extern_t {
|
||||
&m.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_type(m: &wasm_memory_t) -> Box<wasm_memorytype_t> {
|
||||
let ty = m.memory().borrow().ty().clone();
|
||||
Box::new(wasm_memorytype_t::new(ty))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_data(m: &wasm_memory_t) -> *mut u8 {
|
||||
m.memory().borrow().data_ptr()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_data_size(m: &wasm_memory_t) -> usize {
|
||||
m.memory().borrow().data_size()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_size(m: &wasm_memory_t) -> wasm_memory_pages_t {
|
||||
m.memory().borrow().size()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memory_grow(m: &wasm_memory_t, delta: wasm_memory_pages_t) -> bool {
|
||||
m.memory().borrow().grow(delta).is_ok()
|
||||
}
|
||||
71
crates/c-api/src/module.rs
Normal file
71
crates/c-api/src/module.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use crate::{wasm_byte_vec_t, wasm_exporttype_vec_t, wasm_importtype_vec_t};
|
||||
use crate::{wasm_exporttype_t, wasm_importtype_t, wasm_store_t};
|
||||
use wasmtime::{HostRef, Module};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_module_t {
|
||||
pub(crate) module: HostRef<Module>,
|
||||
pub(crate) imports: Vec<wasm_importtype_t>,
|
||||
pub(crate) exports: Vec<wasm_exporttype_t>,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_module_t);
|
||||
|
||||
impl wasm_module_t {
|
||||
fn anyref(&self) -> wasmtime::AnyRef {
|
||||
self.module.anyref()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_new(
|
||||
store: &wasm_store_t,
|
||||
binary: &wasm_byte_vec_t,
|
||||
) -> Option<Box<wasm_module_t>> {
|
||||
let binary = binary.as_slice();
|
||||
let store = &store.store.borrow();
|
||||
let module = Module::from_binary(store, binary).ok()?;
|
||||
let imports = module
|
||||
.imports()
|
||||
.iter()
|
||||
.map(|i| wasm_importtype_t::new(i.clone()))
|
||||
.collect::<Vec<_>>();
|
||||
let exports = module
|
||||
.exports()
|
||||
.iter()
|
||||
.map(|e| wasm_exporttype_t::new(e.clone()))
|
||||
.collect::<Vec<_>>();
|
||||
Some(Box::new(wasm_module_t {
|
||||
module: HostRef::new(module),
|
||||
imports,
|
||||
exports,
|
||||
}))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_validate(store: &wasm_store_t, binary: &wasm_byte_vec_t) -> bool {
|
||||
let binary = binary.as_slice();
|
||||
let store = &store.store.borrow();
|
||||
Module::validate(store, binary).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_exports(module: &wasm_module_t, out: &mut wasm_exporttype_vec_t) {
|
||||
let buffer = module
|
||||
.exports
|
||||
.iter()
|
||||
.map(|et| Some(Box::new(et.clone())))
|
||||
.collect::<Vec<_>>();
|
||||
out.set_buffer(buffer);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_module_imports(module: &wasm_module_t, out: &mut wasm_importtype_vec_t) {
|
||||
let buffer = module
|
||||
.imports
|
||||
.iter()
|
||||
.map(|it| Some(Box::new(it.clone())))
|
||||
.collect::<Vec<_>>();
|
||||
out.set_buffer(buffer);
|
||||
}
|
||||
64
crates/c-api/src/ref.rs
Normal file
64
crates/c-api/src/ref.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
use crate::HostInfoState;
|
||||
use std::os::raw::c_void;
|
||||
use wasmtime::AnyRef;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_ref_t {
|
||||
pub(crate) r: AnyRef,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_own!(wasm_ref_t);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_copy(r: &wasm_ref_t) -> Box<wasm_ref_t> {
|
||||
Box::new(r.clone())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_same(a: &wasm_ref_t, b: &wasm_ref_t) -> bool {
|
||||
a.r.ptr_eq(&b.r)
|
||||
}
|
||||
|
||||
pub(crate) fn get_host_info(r: &AnyRef) -> *mut c_void {
|
||||
let host_info = match r.host_info() {
|
||||
Some(info) => info,
|
||||
None => return std::ptr::null_mut(),
|
||||
};
|
||||
match host_info.downcast_ref::<HostInfoState>() {
|
||||
Some(state) => state.info,
|
||||
None => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_get_host_info(a: &wasm_ref_t) -> *mut c_void {
|
||||
get_host_info(&a.r)
|
||||
}
|
||||
|
||||
pub(crate) fn set_host_info(
|
||||
r: &AnyRef,
|
||||
info: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
) {
|
||||
let info = if info.is_null() && finalizer.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(Box::new(crate::HostInfoState { info, finalizer }) as Box<dyn std::any::Any>)
|
||||
};
|
||||
r.set_host_info(info);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_set_host_info(a: &wasm_ref_t, info: *mut c_void) {
|
||||
set_host_info(&a.r, info, None)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_ref_set_host_info_with_finalizer(
|
||||
a: &wasm_ref_t,
|
||||
info: *mut c_void,
|
||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||
) {
|
||||
set_host_info(&a.r, info, finalizer)
|
||||
}
|
||||
18
crates/c-api/src/store.rs
Normal file
18
crates/c-api/src/store.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use crate::wasm_engine_t;
|
||||
use wasmtime::{HostRef, Store};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_store_t {
|
||||
pub(crate) store: HostRef<Store>,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_own!(wasm_store_t);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_store_new(engine: &wasm_engine_t) -> Box<wasm_store_t> {
|
||||
let engine = &engine.engine;
|
||||
Box::new(wasm_store_t {
|
||||
store: HostRef::new(Store::new(&engine.borrow())),
|
||||
})
|
||||
}
|
||||
120
crates/c-api/src/table.rs
Normal file
120
crates/c-api/src/table.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
use crate::wasm_ref_t;
|
||||
use crate::{wasm_extern_t, wasm_store_t, wasm_tabletype_t, ExternHost};
|
||||
use std::ptr;
|
||||
use wasmtime::{AnyRef, HostRef, Table, Val};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_table_t {
|
||||
ext: wasm_extern_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_table_t);
|
||||
|
||||
pub type wasm_table_size_t = u32;
|
||||
|
||||
impl wasm_table_t {
|
||||
pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_table_t> {
|
||||
match &e.which {
|
||||
ExternHost::Table(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn table(&self) -> &HostRef<Table> {
|
||||
match &self.ext.which {
|
||||
ExternHost::Table(t) => t,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
|
||||
fn anyref(&self) -> wasmtime::AnyRef {
|
||||
self.table().anyref()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_table_new(
|
||||
store: &wasm_store_t,
|
||||
tt: &wasm_tabletype_t,
|
||||
init: *mut wasm_ref_t,
|
||||
) -> Option<Box<wasm_table_t>> {
|
||||
let init: Val = if !init.is_null() {
|
||||
Box::from_raw(init).r.into()
|
||||
} else {
|
||||
Val::AnyRef(AnyRef::Null)
|
||||
};
|
||||
let table = Table::new(&store.store.borrow(), tt.ty().ty.clone(), init).ok()?;
|
||||
Some(Box::new(wasm_table_t {
|
||||
ext: wasm_extern_t {
|
||||
which: ExternHost::Table(HostRef::new(table)),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_table_type(t: &wasm_table_t) -> Box<wasm_tabletype_t> {
|
||||
let ty = t.table().borrow().ty().clone();
|
||||
Box::new(wasm_tabletype_t::new(ty))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_table_get(
|
||||
t: &wasm_table_t,
|
||||
index: wasm_table_size_t,
|
||||
) -> *mut wasm_ref_t {
|
||||
match t.table().borrow().get(index) {
|
||||
Some(val) => into_funcref(val),
|
||||
None => into_funcref(Val::AnyRef(AnyRef::Null)),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_table_set(
|
||||
t: &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).is_ok()
|
||||
}
|
||||
|
||||
unsafe fn into_funcref(val: Val) -> *mut wasm_ref_t {
|
||||
if let Val::AnyRef(AnyRef::Null) = val {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let anyref = match val.anyref() {
|
||||
Some(anyref) => anyref,
|
||||
None => return ptr::null_mut(),
|
||||
};
|
||||
let r = Box::new(wasm_ref_t { r: anyref });
|
||||
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 extern "C" fn wasm_table_size(t: &wasm_table_t) -> wasm_table_size_t {
|
||||
t.table().borrow().size()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_table_grow(
|
||||
t: &wasm_table_t,
|
||||
delta: wasm_table_size_t,
|
||||
init: *mut wasm_ref_t,
|
||||
) -> bool {
|
||||
let init = from_funcref(init);
|
||||
t.table().borrow().grow(delta, init).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_table_as_extern(t: &wasm_table_t) -> &wasm_extern_t {
|
||||
&t.ext
|
||||
}
|
||||
80
crates/c-api/src/trap.rs
Normal file
80
crates/c-api/src/trap.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t};
|
||||
use wasmtime::{HostRef, Trap};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_trap_t {
|
||||
pub(crate) trap: HostRef<Trap>,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_trap_t);
|
||||
|
||||
impl wasm_trap_t {
|
||||
fn anyref(&self) -> wasmtime::AnyRef {
|
||||
self.trap.anyref()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_frame_t {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_own!(wasm_frame_t);
|
||||
|
||||
pub type wasm_message_t = wasm_name_t;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_trap_new(
|
||||
_store: &wasm_store_t,
|
||||
message: &wasm_message_t,
|
||||
) -> Box<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[..message.len() - 1]);
|
||||
Box::new(wasm_trap_t {
|
||||
trap: HostRef::new(Trap::new(message)),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_trap_message(trap: &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 extern "C" fn wasm_trap_origin(_trap: &wasm_trap_t) -> Option<Box<wasm_frame_t>> {
|
||||
None
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_trap_trace(_trap: &wasm_trap_t, out: &mut wasm_frame_vec_t) {
|
||||
out.set_buffer(Vec::new());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_frame_func_index(_arg1: *const wasm_frame_t) -> u32 {
|
||||
unimplemented!("wasm_frame_func_index")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_frame_func_offset(_arg1: *const wasm_frame_t) -> usize {
|
||||
unimplemented!("wasm_frame_func_offset")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_frame_instance(_arg1: *const wasm_frame_t) -> *mut wasm_instance_t {
|
||||
unimplemented!("wasm_frame_instance")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_frame_module_offset(_arg1: *const wasm_frame_t) -> usize {
|
||||
unimplemented!("wasm_frame_module_offset")
|
||||
}
|
||||
36
crates/c-api/src/types.rs
Normal file
36
crates/c-api/src/types.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use wasmtime::Limits;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_limits_t {
|
||||
pub min: u32,
|
||||
pub max: u32,
|
||||
}
|
||||
|
||||
impl wasm_limits_t {
|
||||
pub(crate) fn to_wasmtime(&self) -> Limits {
|
||||
let max = if self.max == u32::max_value() {
|
||||
None
|
||||
} else {
|
||||
Some(self.max)
|
||||
};
|
||||
Limits::new(self.min, max)
|
||||
}
|
||||
}
|
||||
|
||||
mod export;
|
||||
mod r#extern;
|
||||
mod func;
|
||||
mod global;
|
||||
mod import;
|
||||
mod memory;
|
||||
mod table;
|
||||
mod val;
|
||||
pub use self::export::*;
|
||||
pub use self::func::*;
|
||||
pub use self::global::*;
|
||||
pub use self::import::*;
|
||||
pub use self::memory::*;
|
||||
pub use self::r#extern::*;
|
||||
pub use self::table::*;
|
||||
pub use self::val::*;
|
||||
47
crates/c-api/src/types/export.rs
Normal file
47
crates/c-api/src/types/export.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
use crate::{wasm_externtype_t, wasm_name_t};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use std::str;
|
||||
use wasmtime::ExportType;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_exporttype_t {
|
||||
ty: ExportType,
|
||||
name_cache: OnceCell<wasm_name_t>,
|
||||
type_cache: OnceCell<wasm_externtype_t>,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_exporttype_t);
|
||||
|
||||
impl wasm_exporttype_t {
|
||||
pub(crate) fn new(ty: ExportType) -> wasm_exporttype_t {
|
||||
wasm_exporttype_t {
|
||||
ty,
|
||||
name_cache: OnceCell::new(),
|
||||
type_cache: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_exporttype_new(
|
||||
name: &mut wasm_name_t,
|
||||
ty: Box<wasm_externtype_t>,
|
||||
) -> Option<Box<wasm_exporttype_t>> {
|
||||
let name = name.take();
|
||||
let name = str::from_utf8(&name).ok()?;
|
||||
let ty = ExportType::new(name, ty.ty());
|
||||
Some(Box::new(wasm_exporttype_t::new(ty)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_exporttype_name(et: &wasm_exporttype_t) -> &wasm_name_t {
|
||||
et.name_cache
|
||||
.get_or_init(|| wasm_name_t::from_name(&et.ty.name()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_exporttype_type(et: &wasm_exporttype_t) -> &wasm_externtype_t {
|
||||
et.type_cache
|
||||
.get_or_init(|| wasm_externtype_t::new(et.ty.ty().clone()))
|
||||
}
|
||||
112
crates/c-api/src/types/extern.rs
Normal file
112
crates/c-api/src/types/extern.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use crate::{wasm_functype_t, wasm_globaltype_t, wasm_memorytype_t, wasm_tabletype_t};
|
||||
use crate::{CFuncType, CGlobalType, CMemoryType, CTableType};
|
||||
use wasmtime::ExternType;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_externtype_t {
|
||||
pub(crate) which: CExternType,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_externtype_t);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum CExternType {
|
||||
Func(CFuncType),
|
||||
Global(CGlobalType),
|
||||
Memory(CMemoryType),
|
||||
Table(CTableType),
|
||||
}
|
||||
|
||||
pub type wasm_externkind_t = u8;
|
||||
|
||||
pub const WASM_EXTERN_FUNC: wasm_externkind_t = 0;
|
||||
pub const WASM_EXTERN_GLOBAL: wasm_externkind_t = 1;
|
||||
pub const WASM_EXTERN_TABLE: wasm_externkind_t = 2;
|
||||
pub const WASM_EXTERN_MEMORY: wasm_externkind_t = 3;
|
||||
|
||||
impl wasm_externtype_t {
|
||||
pub(crate) fn new(ty: ExternType) -> wasm_externtype_t {
|
||||
wasm_externtype_t {
|
||||
which: match ty {
|
||||
ExternType::Func(f) => CExternType::Func(CFuncType::new(f)),
|
||||
ExternType::Global(f) => CExternType::Global(CGlobalType::new(f)),
|
||||
ExternType::Memory(f) => CExternType::Memory(CMemoryType::new(f)),
|
||||
ExternType::Table(f) => CExternType::Table(CTableType::new(f)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ty(&self) -> ExternType {
|
||||
match &self.which {
|
||||
CExternType::Func(f) => ExternType::Func(f.ty.clone()),
|
||||
CExternType::Table(f) => ExternType::Table(f.ty.clone()),
|
||||
CExternType::Global(f) => ExternType::Global(f.ty.clone()),
|
||||
CExternType::Memory(f) => ExternType::Memory(f.ty.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_kind(et: &wasm_externtype_t) -> wasm_externkind_t {
|
||||
match &et.which {
|
||||
CExternType::Func(_) => WASM_EXTERN_FUNC,
|
||||
CExternType::Table(_) => WASM_EXTERN_TABLE,
|
||||
CExternType::Global(_) => WASM_EXTERN_GLOBAL,
|
||||
CExternType::Memory(_) => WASM_EXTERN_MEMORY,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_functype(et: &wasm_externtype_t) -> Option<&wasm_functype_t> {
|
||||
wasm_externtype_as_functype_const(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_functype_const(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_functype_t> {
|
||||
wasm_functype_t::try_from(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_globaltype(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_globaltype_t> {
|
||||
wasm_externtype_as_globaltype_const(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_globaltype_const(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_globaltype_t> {
|
||||
wasm_globaltype_t::try_from(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_tabletype(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_tabletype_t> {
|
||||
wasm_externtype_as_tabletype_const(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_tabletype_const(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_tabletype_t> {
|
||||
wasm_tabletype_t::try_from(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_memorytype(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_memorytype_t> {
|
||||
wasm_externtype_as_memorytype_const(et)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_externtype_as_memorytype_const(
|
||||
et: &wasm_externtype_t,
|
||||
) -> Option<&wasm_memorytype_t> {
|
||||
wasm_memorytype_t::try_from(et)
|
||||
}
|
||||
105
crates/c-api/src/types/func.rs
Normal file
105
crates/c-api/src/types/func.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
use crate::{wasm_externtype_t, wasm_valtype_t, wasm_valtype_vec_t, CExternType};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use wasmtime::FuncType;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_functype_t {
|
||||
ext: wasm_externtype_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_functype_t);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CFuncType {
|
||||
pub(crate) ty: FuncType,
|
||||
params_cache: OnceCell<wasm_valtype_vec_t>,
|
||||
returns_cache: OnceCell<wasm_valtype_vec_t>,
|
||||
}
|
||||
|
||||
impl wasm_functype_t {
|
||||
pub(crate) fn new(ty: FuncType) -> wasm_functype_t {
|
||||
wasm_functype_t {
|
||||
ext: wasm_externtype_t::new(ty.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_functype_t> {
|
||||
match &e.which {
|
||||
CExternType::Func(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ty(&self) -> &CFuncType {
|
||||
match &self.ext.which {
|
||||
CExternType::Func(f) => &f,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CFuncType {
|
||||
pub(crate) fn new(ty: FuncType) -> CFuncType {
|
||||
CFuncType {
|
||||
ty,
|
||||
params_cache: OnceCell::new(),
|
||||
returns_cache: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_functype_new(
|
||||
params: &mut wasm_valtype_vec_t,
|
||||
results: &mut wasm_valtype_vec_t,
|
||||
) -> Box<wasm_functype_t> {
|
||||
let params = params
|
||||
.take()
|
||||
.into_iter()
|
||||
.map(|vt| vt.unwrap().ty.clone())
|
||||
.collect::<Vec<_>>();
|
||||
let results = results
|
||||
.take()
|
||||
.into_iter()
|
||||
.map(|vt| vt.unwrap().ty.clone())
|
||||
.collect::<Vec<_>>();
|
||||
let functype = FuncType::new(params.into_boxed_slice(), results.into_boxed_slice());
|
||||
Box::new(wasm_functype_t::new(functype))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> &wasm_valtype_vec_t {
|
||||
let ft = ft.ty();
|
||||
ft.params_cache.get_or_init(|| {
|
||||
ft.ty
|
||||
.params()
|
||||
.iter()
|
||||
.map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> &wasm_valtype_vec_t {
|
||||
let ft = ft.ty();
|
||||
ft.returns_cache.get_or_init(|| {
|
||||
ft.ty
|
||||
.results()
|
||||
.iter()
|
||||
.map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_functype_as_externtype(ty: &wasm_functype_t) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_functype_as_externtype_const(ty: &wasm_functype_t) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
98
crates/c-api/src/types/global.rs
Normal file
98
crates/c-api/src/types/global.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
use crate::{wasm_externtype_t, wasm_valtype_t, CExternType};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use wasmtime::GlobalType;
|
||||
|
||||
pub type wasm_mutability_t = u8;
|
||||
|
||||
pub const WASM_CONST: wasm_mutability_t = 0;
|
||||
pub const WASM_VAR: wasm_mutability_t = 1;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_globaltype_t {
|
||||
ext: wasm_externtype_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_globaltype_t);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CGlobalType {
|
||||
pub(crate) ty: GlobalType,
|
||||
content_cache: OnceCell<wasm_valtype_t>,
|
||||
}
|
||||
|
||||
impl wasm_globaltype_t {
|
||||
pub(crate) fn new(ty: GlobalType) -> wasm_globaltype_t {
|
||||
wasm_globaltype_t {
|
||||
ext: wasm_externtype_t::new(ty.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_globaltype_t> {
|
||||
match &e.which {
|
||||
CExternType::Global(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ty(&self) -> &CGlobalType {
|
||||
match &self.ext.which {
|
||||
CExternType::Global(f) => &f,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CGlobalType {
|
||||
pub(crate) fn new(ty: GlobalType) -> CGlobalType {
|
||||
CGlobalType {
|
||||
ty,
|
||||
content_cache: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_globaltype_new(
|
||||
ty: Box<wasm_valtype_t>,
|
||||
mutability: wasm_mutability_t,
|
||||
) -> Option<Box<wasm_globaltype_t>> {
|
||||
use wasmtime::Mutability::*;
|
||||
let mutability = match mutability {
|
||||
WASM_CONST => Const,
|
||||
WASM_VAR => Var,
|
||||
_ => return None,
|
||||
};
|
||||
let ty = GlobalType::new(ty.ty.clone(), mutability);
|
||||
Some(Box::new(wasm_globaltype_t::new(ty)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_globaltype_content(gt: &wasm_globaltype_t) -> &wasm_valtype_t {
|
||||
let gt = gt.ty();
|
||||
gt.content_cache.get_or_init(|| wasm_valtype_t {
|
||||
ty: gt.ty.content().clone(),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_globaltype_mutability(gt: &wasm_globaltype_t) -> wasm_mutability_t {
|
||||
use wasmtime::Mutability::*;
|
||||
let gt = gt.ty();
|
||||
match gt.ty.mutability() {
|
||||
Const => WASM_CONST,
|
||||
Var => WASM_VAR,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_globaltype_as_externtype(ty: &wasm_globaltype_t) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_globaltype_as_externtype_const(
|
||||
ty: &wasm_globaltype_t,
|
||||
) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
58
crates/c-api/src/types/import.rs
Normal file
58
crates/c-api/src/types/import.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use crate::{wasm_externtype_t, wasm_name_t};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use std::str;
|
||||
use wasmtime::ImportType;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_importtype_t {
|
||||
pub(crate) ty: ImportType,
|
||||
module_cache: OnceCell<wasm_name_t>,
|
||||
name_cache: OnceCell<wasm_name_t>,
|
||||
type_cache: OnceCell<wasm_externtype_t>,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_importtype_t);
|
||||
|
||||
impl wasm_importtype_t {
|
||||
pub(crate) fn new(ty: ImportType) -> wasm_importtype_t {
|
||||
wasm_importtype_t {
|
||||
ty,
|
||||
module_cache: OnceCell::new(),
|
||||
name_cache: OnceCell::new(),
|
||||
type_cache: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_new(
|
||||
module: &mut wasm_name_t,
|
||||
name: &mut wasm_name_t,
|
||||
ty: Box<wasm_externtype_t>,
|
||||
) -> Option<Box<wasm_importtype_t>> {
|
||||
let module = module.take();
|
||||
let name = name.take();
|
||||
let module = str::from_utf8(&module).ok()?;
|
||||
let name = str::from_utf8(&name).ok()?;
|
||||
let ty = ImportType::new(module, name, ty.ty());
|
||||
Some(Box::new(wasm_importtype_t::new(ty)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_module(it: &wasm_importtype_t) -> &wasm_name_t {
|
||||
it.module_cache
|
||||
.get_or_init(|| wasm_name_t::from_name(&it.ty.module()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_name(it: &wasm_importtype_t) -> &wasm_name_t {
|
||||
it.name_cache
|
||||
.get_or_init(|| wasm_name_t::from_name(&it.ty.name()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_type(it: &wasm_importtype_t) -> &wasm_externtype_t {
|
||||
it.type_cache
|
||||
.get_or_init(|| wasm_externtype_t::new(it.ty.ty().clone()))
|
||||
}
|
||||
79
crates/c-api/src/types/memory.rs
Normal file
79
crates/c-api/src/types/memory.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use crate::{wasm_externtype_t, wasm_limits_t, CExternType};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use wasmtime::MemoryType;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_memorytype_t {
|
||||
ext: wasm_externtype_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_memorytype_t);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CMemoryType {
|
||||
pub(crate) ty: MemoryType,
|
||||
limits_cache: OnceCell<wasm_limits_t>,
|
||||
}
|
||||
|
||||
impl wasm_memorytype_t {
|
||||
pub(crate) fn new(ty: MemoryType) -> wasm_memorytype_t {
|
||||
wasm_memorytype_t {
|
||||
ext: wasm_externtype_t::new(ty.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_memorytype_t> {
|
||||
match &e.which {
|
||||
CExternType::Memory(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ty(&self) -> &CMemoryType {
|
||||
match &self.ext.which {
|
||||
CExternType::Memory(f) => &f,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CMemoryType {
|
||||
pub(crate) fn new(ty: MemoryType) -> CMemoryType {
|
||||
CMemoryType {
|
||||
ty,
|
||||
limits_cache: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box<wasm_memorytype_t> {
|
||||
Box::new(wasm_memorytype_t::new(MemoryType::new(
|
||||
limits.to_wasmtime(),
|
||||
)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> &wasm_limits_t {
|
||||
let mt = mt.ty();
|
||||
mt.limits_cache.get_or_init(|| {
|
||||
let limits = mt.ty.limits();
|
||||
wasm_limits_t {
|
||||
min: limits.min(),
|
||||
max: limits.max().unwrap_or(u32::max_value()),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memorytype_as_externtype(ty: &wasm_memorytype_t) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_memorytype_as_externtype_const(
|
||||
ty: &wasm_memorytype_t,
|
||||
) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
91
crates/c-api/src/types/table.rs
Normal file
91
crates/c-api/src/types/table.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
use crate::{wasm_externtype_t, wasm_limits_t, wasm_valtype_t, CExternType};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use wasmtime::TableType;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_tabletype_t {
|
||||
ext: wasm_externtype_t,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_tabletype_t);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CTableType {
|
||||
pub(crate) ty: TableType,
|
||||
element_cache: OnceCell<wasm_valtype_t>,
|
||||
limits_cache: OnceCell<wasm_limits_t>,
|
||||
}
|
||||
|
||||
impl wasm_tabletype_t {
|
||||
pub(crate) fn new(ty: TableType) -> wasm_tabletype_t {
|
||||
wasm_tabletype_t {
|
||||
ext: wasm_externtype_t::new(ty.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_tabletype_t> {
|
||||
match &e.which {
|
||||
CExternType::Table(_) => Some(unsafe { &*(e as *const _ as *const _) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ty(&self) -> &CTableType {
|
||||
match &self.ext.which {
|
||||
CExternType::Table(f) => &f,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CTableType {
|
||||
pub(crate) fn new(ty: TableType) -> CTableType {
|
||||
CTableType {
|
||||
ty,
|
||||
element_cache: OnceCell::new(),
|
||||
limits_cache: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_tabletype_new(
|
||||
ty: Box<wasm_valtype_t>,
|
||||
limits: &wasm_limits_t,
|
||||
) -> Box<wasm_tabletype_t> {
|
||||
Box::new(wasm_tabletype_t::new(TableType::new(
|
||||
ty.ty,
|
||||
limits.to_wasmtime(),
|
||||
)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_tabletype_element(tt: &wasm_tabletype_t) -> &wasm_valtype_t {
|
||||
let tt = tt.ty();
|
||||
tt.element_cache.get_or_init(|| wasm_valtype_t {
|
||||
ty: tt.ty.element().clone(),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_tabletype_limits(tt: &wasm_tabletype_t) -> &wasm_limits_t {
|
||||
let tt = tt.ty();
|
||||
tt.limits_cache.get_or_init(|| {
|
||||
let limits = tt.ty.limits();
|
||||
wasm_limits_t {
|
||||
min: limits.min(),
|
||||
max: limits.max().unwrap_or(u32::max_value()),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_tabletype_as_externtype(ty: &wasm_tabletype_t) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_tabletype_as_externtype_const(ty: &wasm_tabletype_t) -> &wasm_externtype_t {
|
||||
&ty.ext
|
||||
}
|
||||
53
crates/c-api/src/types/val.rs
Normal file
53
crates/c-api/src/types/val.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use wasmtime::ValType;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_valtype_t {
|
||||
pub(crate) ty: ValType,
|
||||
}
|
||||
|
||||
wasmtime_c_api_macros::declare_ty!(wasm_valtype_t);
|
||||
|
||||
pub type wasm_valkind_t = u8;
|
||||
pub const WASM_I32: wasm_valkind_t = 0;
|
||||
pub const WASM_I64: wasm_valkind_t = 1;
|
||||
pub const WASM_F32: wasm_valkind_t = 2;
|
||||
pub const WASM_F64: wasm_valkind_t = 3;
|
||||
pub const WASM_ANYREF: wasm_valkind_t = 128;
|
||||
pub const WASM_FUNCREF: wasm_valkind_t = 129;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Box<wasm_valtype_t> {
|
||||
Box::new(wasm_valtype_t {
|
||||
ty: into_valtype(kind),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_valtype_kind(vt: &wasm_valtype_t) -> wasm_valkind_t {
|
||||
from_valtype(&vt.ty)
|
||||
}
|
||||
|
||||
pub(crate) fn into_valtype(kind: wasm_valkind_t) -> ValType {
|
||||
match kind {
|
||||
WASM_I32 => ValType::I32,
|
||||
WASM_I64 => ValType::I64,
|
||||
WASM_F32 => ValType::F32,
|
||||
WASM_F64 => ValType::F64,
|
||||
WASM_ANYREF => ValType::AnyRef,
|
||||
WASM_FUNCREF => ValType::FuncRef,
|
||||
_ => panic!("unexpected kind: {}", kind),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_valtype(ty: &ValType) -> wasm_valkind_t {
|
||||
match ty {
|
||||
ValType::I32 => WASM_I32,
|
||||
ValType::I64 => WASM_I64,
|
||||
ValType::F32 => WASM_F32,
|
||||
ValType::F64 => WASM_F64,
|
||||
ValType::AnyRef => WASM_ANYREF,
|
||||
ValType::FuncRef => WASM_FUNCREF,
|
||||
_ => panic!("wasm_valkind_t has no known conversion for {:?}", ty),
|
||||
}
|
||||
}
|
||||
99
crates/c-api/src/val.rs
Normal file
99
crates/c-api/src/val.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use crate::{from_valtype, into_valtype, wasm_ref_t, wasm_valkind_t, WASM_I32};
|
||||
use wasmtime::{Val, ValType};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct wasm_val_t {
|
||||
pub kind: wasm_valkind_t,
|
||||
pub of: wasm_val_union,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union wasm_val_union {
|
||||
pub i32: i32,
|
||||
pub i64: i64,
|
||||
pub u32: u32,
|
||||
pub u64: u64,
|
||||
pub f32: f32,
|
||||
pub f64: f64,
|
||||
pub ref_: *mut wasm_ref_t,
|
||||
}
|
||||
|
||||
impl Default for wasm_val_t {
|
||||
fn default() -> Self {
|
||||
wasm_val_t {
|
||||
kind: WASM_I32,
|
||||
of: wasm_val_union { i32: 0 },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl wasm_val_t {
|
||||
pub fn from_val(val: &Val) -> wasm_val_t {
|
||||
match val {
|
||||
Val::I32(i) => wasm_val_t {
|
||||
kind: from_valtype(&ValType::I32),
|
||||
of: wasm_val_union { i32: *i },
|
||||
},
|
||||
Val::I64(i) => wasm_val_t {
|
||||
kind: from_valtype(&ValType::I64),
|
||||
of: wasm_val_union { i64: *i },
|
||||
},
|
||||
Val::F32(f) => wasm_val_t {
|
||||
kind: from_valtype(&ValType::F32),
|
||||
of: wasm_val_union { u32: *f },
|
||||
},
|
||||
Val::F64(f) => wasm_val_t {
|
||||
kind: from_valtype(&ValType::F64),
|
||||
of: wasm_val_union { u64: *f },
|
||||
},
|
||||
_ => unimplemented!("wasm_val_t::from_val {:?}", val),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, val: Val) {
|
||||
match val {
|
||||
Val::I32(i) => {
|
||||
self.kind = from_valtype(&ValType::I32);
|
||||
self.of = wasm_val_union { i32: i };
|
||||
}
|
||||
Val::I64(i) => {
|
||||
self.kind = from_valtype(&ValType::I64);
|
||||
self.of = wasm_val_union { i64: i };
|
||||
}
|
||||
Val::F32(f) => {
|
||||
self.kind = from_valtype(&ValType::F32);
|
||||
self.of = wasm_val_union { u32: f };
|
||||
}
|
||||
Val::F64(f) => {
|
||||
self.kind = from_valtype(&ValType::F64);
|
||||
self.of = wasm_val_union { u64: f };
|
||||
}
|
||||
_ => unimplemented!("wasm_val_t::from_val {:?}", val),
|
||||
}
|
||||
}
|
||||
|
||||
pub 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_val_copy(out: *mut wasm_val_t, source: &wasm_val_t) {
|
||||
*out = match into_valtype(source.kind) {
|
||||
ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 => *source,
|
||||
_ => unimplemented!("wasm_val_copy arg"),
|
||||
};
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_val_delete(_val: &mut wasm_val_t) {
|
||||
// currently we only support integers/floats which need no deletion
|
||||
}
|
||||
221
crates/c-api/src/vec.rs
Normal file
221
crates/c-api/src/vec.rs
Normal file
@@ -0,0 +1,221 @@
|
||||
use crate::wasm_valtype_t;
|
||||
use crate::{wasm_exporttype_t, wasm_extern_t, wasm_frame_t, wasm_val_t};
|
||||
use crate::{wasm_externtype_t, wasm_importtype_t, wasm_memorytype_t};
|
||||
use crate::{wasm_functype_t, wasm_globaltype_t, wasm_tabletype_t};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
pub type wasm_name_t = wasm_byte_vec_t;
|
||||
|
||||
impl wasm_name_t {
|
||||
pub(crate) fn from_name(name: &str) -> wasm_name_t {
|
||||
name.to_string().into_bytes().into()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! declare_vecs {
|
||||
(
|
||||
$((
|
||||
name: $name:ident,
|
||||
ty: $elem_ty:ty,
|
||||
new: $new:ident,
|
||||
empty: $empty:ident,
|
||||
uninit: $uninit:ident,
|
||||
copy: $copy:ident,
|
||||
delete: $delete:ident,
|
||||
))*
|
||||
) => {$(
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct $name {
|
||||
size: usize,
|
||||
data: *mut $elem_ty,
|
||||
}
|
||||
|
||||
impl $name {
|
||||
pub fn set_buffer(&mut self, buffer: Vec<$elem_ty>) {
|
||||
let mut vec = buffer.into_boxed_slice();
|
||||
self.size = vec.len();
|
||||
self.data = vec.as_mut_ptr();
|
||||
mem::forget(vec);
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[$elem_ty] {
|
||||
unsafe { slice::from_raw_parts(self.data, self.size) }
|
||||
}
|
||||
|
||||
pub fn take(&mut self) -> Vec<$elem_ty> {
|
||||
if self.data.is_null() {
|
||||
return Vec::new();
|
||||
}
|
||||
let vec = unsafe {
|
||||
Vec::from_raw_parts(self.data, self.size, self.size)
|
||||
};
|
||||
self.data = ptr::null_mut();
|
||||
self.size = 0;
|
||||
return vec;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<$elem_ty>> for $name {
|
||||
fn from(mut vec: Vec<$elem_ty>) -> Self {
|
||||
assert_eq!(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) {
|
||||
drop(self.take());
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn $empty(out: &mut $name) {
|
||||
out.size = 0;
|
||||
out.data = ptr::null_mut();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn $uninit(out: &mut $name, size: usize) {
|
||||
out.set_buffer(vec![Default::default(); size]);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn $new(
|
||||
out: &mut $name,
|
||||
size: usize,
|
||||
ptr: *const $elem_ty,
|
||||
) {
|
||||
let slice = slice::from_raw_parts(ptr, size);
|
||||
out.set_buffer(slice.to_vec());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn $copy(out: &mut $name, src: &$name) {
|
||||
out.set_buffer(src.as_slice().to_vec());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn $delete(out: &mut $name) {
|
||||
out.take();
|
||||
}
|
||||
)*};
|
||||
}
|
||||
|
||||
declare_vecs! {
|
||||
(
|
||||
name: wasm_byte_vec_t,
|
||||
ty: u8,
|
||||
new: wasm_byte_vec_new,
|
||||
empty: wasm_byte_vec_new_empty,
|
||||
uninit: wasm_byte_vec_new_uninitialized,
|
||||
copy: wasm_byte_vec_copy,
|
||||
delete: wasm_byte_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_valtype_vec_t,
|
||||
ty: Option<Box<wasm_valtype_t>>,
|
||||
new: wasm_valtype_vec_new,
|
||||
empty: wasm_valtype_vec_new_empty,
|
||||
uninit: wasm_valtype_vec_new_uninitialized,
|
||||
copy: wasm_valtype_vec_copy,
|
||||
delete: wasm_valtype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_functype_vec_t,
|
||||
ty: Option<Box<wasm_functype_t>>,
|
||||
new: wasm_functype_vec_new,
|
||||
empty: wasm_functype_vec_new_empty,
|
||||
uninit: wasm_functype_vec_new_uninitialized,
|
||||
copy: wasm_functype_vec_copy,
|
||||
delete: wasm_functype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_globaltype_vec_t,
|
||||
ty: Option<Box<wasm_globaltype_t>>,
|
||||
new: wasm_globaltype_vec_new,
|
||||
empty: wasm_globaltype_vec_new_empty,
|
||||
uninit: wasm_globaltype_vec_new_uninitialized,
|
||||
copy: wasm_globaltype_vec_copy,
|
||||
delete: wasm_globaltype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_tabletype_vec_t,
|
||||
ty: Option<Box<wasm_tabletype_t>>,
|
||||
new: wasm_tabletype_vec_new,
|
||||
empty: wasm_tabletype_vec_new_empty,
|
||||
uninit: wasm_tabletype_vec_new_uninitialized,
|
||||
copy: wasm_tabletype_vec_copy,
|
||||
delete: wasm_tabletype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_memorytype_vec_t,
|
||||
ty: Option<Box<wasm_memorytype_t>>,
|
||||
new: wasm_memorytype_vec_new,
|
||||
empty: wasm_memorytype_vec_new_empty,
|
||||
uninit: wasm_memorytype_vec_new_uninitialized,
|
||||
copy: wasm_memorytype_vec_copy,
|
||||
delete: wasm_memorytype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_externtype_vec_t,
|
||||
ty: Option<Box<wasm_externtype_t>>,
|
||||
new: wasm_externtype_vec_new,
|
||||
empty: wasm_externtype_vec_new_empty,
|
||||
uninit: wasm_externtype_vec_new_uninitialized,
|
||||
copy: wasm_externtype_vec_copy,
|
||||
delete: wasm_externtype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_importtype_vec_t,
|
||||
ty: Option<Box<wasm_importtype_t>>,
|
||||
new: wasm_importtype_vec_new,
|
||||
empty: wasm_importtype_vec_new_empty,
|
||||
uninit: wasm_importtype_vec_new_uninitialized,
|
||||
copy: wasm_importtype_vec_copy,
|
||||
delete: wasm_importtype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_exporttype_vec_t,
|
||||
ty: Option<Box<wasm_exporttype_t>>,
|
||||
new: wasm_exporttype_vec_new,
|
||||
empty: wasm_exporttype_vec_new_empty,
|
||||
uninit: wasm_exporttype_vec_new_uninitialized,
|
||||
copy: wasm_exporttype_vec_copy,
|
||||
delete: wasm_exporttype_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_val_vec_t,
|
||||
ty: wasm_val_t,
|
||||
new: wasm_val_vec_new,
|
||||
empty: wasm_val_vec_new_empty,
|
||||
uninit: wasm_val_vec_new_uninitialized,
|
||||
copy: wasm_val_vec_copy,
|
||||
delete: wasm_val_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_frame_vec_t,
|
||||
ty: Option<Box<wasm_frame_t>>,
|
||||
new: wasm_frame_vec_new,
|
||||
empty: wasm_frame_vec_new_empty,
|
||||
uninit: wasm_frame_vec_new_uninitialized,
|
||||
copy: wasm_frame_vec_copy,
|
||||
delete: wasm_frame_vec_delete,
|
||||
)
|
||||
(
|
||||
name: wasm_extern_vec_t,
|
||||
ty: Option<Box<wasm_extern_t>>,
|
||||
new: wasm_extern_vec_new,
|
||||
empty: wasm_extern_vec_new_empty,
|
||||
uninit: wasm_extern_vec_new_uninitialized,
|
||||
copy: wasm_extern_vec_copy,
|
||||
delete: wasm_extern_vec_delete,
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//! The WASI embedding API definitions for Wasmtime.
|
||||
use crate::{wasm_extern_t, wasm_importtype_t, wasm_store_t, wasm_trap_t, ExternHost, ExternType};
|
||||
use crate::{wasm_extern_t, wasm_importtype_t, wasm_store_t, wasm_trap_t, ExternHost};
|
||||
use anyhow::Result;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::CStr;
|
||||
@@ -50,37 +50,35 @@ pub struct wasi_config_t {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_new() -> *mut wasi_config_t {
|
||||
Box::into_raw(Box::new(wasi_config_t::default()))
|
||||
pub extern "C" fn wasi_config_new() -> Box<wasi_config_t> {
|
||||
Box::new(wasi_config_t::default())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_delete(config: *mut wasi_config_t) {
|
||||
drop(Box::from_raw(config));
|
||||
}
|
||||
pub extern "C" fn wasi_config_delete(_config: Box<wasi_config_t>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_set_argv(
|
||||
config: *mut wasi_config_t,
|
||||
config: &mut wasi_config_t,
|
||||
argc: c_int,
|
||||
argv: *const *const c_char,
|
||||
) {
|
||||
(*config).args = slice::from_raw_parts(argv, argc as usize)
|
||||
config.args = slice::from_raw_parts(argv, argc as usize)
|
||||
.iter()
|
||||
.map(|p| CStr::from_ptr(*p).to_bytes().to_owned())
|
||||
.collect();
|
||||
(*config).inherit_args = false;
|
||||
config.inherit_args = false;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_inherit_argv(config: *mut wasi_config_t) {
|
||||
(*config).args.clear();
|
||||
(*config).inherit_args = true;
|
||||
pub extern "C" fn wasi_config_inherit_argv(config: &mut wasi_config_t) {
|
||||
config.args.clear();
|
||||
config.inherit_args = true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_set_env(
|
||||
config: *mut wasi_config_t,
|
||||
config: &mut wasi_config_t,
|
||||
envc: c_int,
|
||||
names: *const *const c_char,
|
||||
values: *const *const c_char,
|
||||
@@ -88,7 +86,7 @@ pub unsafe extern "C" fn wasi_config_set_env(
|
||||
let names = slice::from_raw_parts(names, envc as usize);
|
||||
let values = slice::from_raw_parts(values, envc as usize);
|
||||
|
||||
(*config).env = names
|
||||
config.env = names
|
||||
.iter()
|
||||
.map(|p| CStr::from_ptr(*p).to_bytes().to_owned())
|
||||
.zip(
|
||||
@@ -97,18 +95,18 @@ pub unsafe extern "C" fn wasi_config_set_env(
|
||||
.map(|p| CStr::from_ptr(*p).to_bytes().to_owned()),
|
||||
)
|
||||
.collect();
|
||||
(*config).inherit_env = false;
|
||||
config.inherit_env = false;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_inherit_env(config: *mut wasi_config_t) {
|
||||
(*config).env.clear();
|
||||
(*config).inherit_env = true;
|
||||
pub extern "C" fn wasi_config_inherit_env(config: &mut wasi_config_t) {
|
||||
config.env.clear();
|
||||
config.inherit_env = true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_set_stdin_file(
|
||||
config: *mut wasi_config_t,
|
||||
config: &mut wasi_config_t,
|
||||
path: *const c_char,
|
||||
) -> bool {
|
||||
let file = match open_file(path) {
|
||||
@@ -116,21 +114,21 @@ pub unsafe extern "C" fn wasi_config_set_stdin_file(
|
||||
None => return false,
|
||||
};
|
||||
|
||||
(*config).stdin = Some(file);
|
||||
(*config).inherit_stdin = false;
|
||||
config.stdin = Some(file);
|
||||
config.inherit_stdin = false;
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_inherit_stdin(config: *mut wasi_config_t) {
|
||||
(*config).stdin = None;
|
||||
(*config).inherit_stdin = true;
|
||||
pub extern "C" fn wasi_config_inherit_stdin(config: &mut wasi_config_t) {
|
||||
config.stdin = None;
|
||||
config.inherit_stdin = true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_set_stdout_file(
|
||||
config: *mut wasi_config_t,
|
||||
config: &mut wasi_config_t,
|
||||
path: *const c_char,
|
||||
) -> bool {
|
||||
let file = match create_file(path) {
|
||||
@@ -138,21 +136,21 @@ pub unsafe extern "C" fn wasi_config_set_stdout_file(
|
||||
None => return false,
|
||||
};
|
||||
|
||||
(*config).stdout = Some(file);
|
||||
(*config).inherit_stdout = false;
|
||||
config.stdout = Some(file);
|
||||
config.inherit_stdout = false;
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_inherit_stdout(config: *mut wasi_config_t) {
|
||||
(*config).stdout = None;
|
||||
(*config).inherit_stdout = true;
|
||||
pub extern "C" fn wasi_config_inherit_stdout(config: &mut wasi_config_t) {
|
||||
config.stdout = None;
|
||||
config.inherit_stdout = true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_set_stderr_file(
|
||||
config: *mut wasi_config_t,
|
||||
config: &mut wasi_config_t,
|
||||
path: *const c_char,
|
||||
) -> bool {
|
||||
let file = match create_file(path) {
|
||||
@@ -167,14 +165,14 @@ pub unsafe extern "C" fn wasi_config_set_stderr_file(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_inherit_stderr(config: *mut wasi_config_t) {
|
||||
(*config).stderr = None;
|
||||
(*config).inherit_stderr = true;
|
||||
pub extern "C" fn wasi_config_inherit_stderr(config: &mut wasi_config_t) {
|
||||
config.stderr = None;
|
||||
config.inherit_stderr = true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_config_preopen_dir(
|
||||
config: *mut wasi_config_t,
|
||||
config: &mut wasi_config_t,
|
||||
path: *const c_char,
|
||||
guest_path: *const c_char,
|
||||
) -> bool {
|
||||
@@ -278,13 +276,12 @@ impl wasi_instance_t {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_instance_new(
|
||||
store: *mut wasm_store_t,
|
||||
store: &wasm_store_t,
|
||||
name: *const c_char,
|
||||
config: *mut wasi_config_t,
|
||||
trap: *mut *mut wasm_trap_t,
|
||||
) -> *mut wasi_instance_t {
|
||||
let store = &(*store).store.borrow();
|
||||
let config = Box::from_raw(config);
|
||||
config: Box<wasi_config_t>,
|
||||
trap: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasi_instance_t>> {
|
||||
let store = &store.store.borrow();
|
||||
|
||||
let result = match CStr::from_ptr(name).to_str().unwrap_or("") {
|
||||
"wasi_snapshot_preview1" => create_preview1_instance(store, *config),
|
||||
@@ -293,70 +290,58 @@ pub unsafe extern "C" fn wasi_instance_new(
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(wasi) => Box::into_raw(Box::new(wasi_instance_t {
|
||||
Ok(wasi) => Some(Box::new(wasi_instance_t {
|
||||
wasi,
|
||||
export_cache: HashMap::new(),
|
||||
})),
|
||||
Err(e) => {
|
||||
(*trap) = Box::into_raw(Box::new(wasm_trap_t {
|
||||
*trap = Box::into_raw(Box::new(wasm_trap_t {
|
||||
trap: HostRef::new(Trap::new(e.to_string())),
|
||||
}));
|
||||
|
||||
std::ptr::null_mut()
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_instance_delete(instance: *mut wasi_instance_t) {
|
||||
drop(Box::from_raw(instance));
|
||||
}
|
||||
pub extern "C" fn wasi_instance_delete(_instance: Box<wasi_instance_t>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasi_instance_bind_import(
|
||||
instance: *mut wasi_instance_t,
|
||||
import: *const wasm_importtype_t,
|
||||
) -> *const wasm_extern_t {
|
||||
// The import should be a function (WASI only exports functions)
|
||||
let func_type = match (*import).ty.ty() {
|
||||
ExternType::Func(f) => f,
|
||||
_ => return std::ptr::null_mut(),
|
||||
};
|
||||
pub extern "C" fn wasi_instance_bind_import<'a>(
|
||||
instance: &'a mut wasi_instance_t,
|
||||
import: &wasm_importtype_t,
|
||||
) -> Option<&'a wasm_extern_t> {
|
||||
let module = import.ty.module();
|
||||
let name = import.ty.name();
|
||||
|
||||
let module = (*import).ty.module();
|
||||
let name = (*import).ty.name();
|
||||
|
||||
let import = match &(*instance).wasi {
|
||||
let export = match &instance.wasi {
|
||||
WasiInstance::Preview1(wasi) => {
|
||||
if module != "wasi_snapshot_preview1" {
|
||||
return std::ptr::null();
|
||||
return None;
|
||||
}
|
||||
wasi.get_export(name)
|
||||
wasi.get_export(name)?
|
||||
}
|
||||
WasiInstance::Snapshot0(wasi) => {
|
||||
if module != "wasi_unstable" {
|
||||
return std::ptr::null();
|
||||
return None;
|
||||
}
|
||||
|
||||
wasi.get_export(name)
|
||||
wasi.get_export(name)?
|
||||
}
|
||||
};
|
||||
|
||||
match import {
|
||||
Some(export) => {
|
||||
if export.ty() != func_type {
|
||||
return std::ptr::null_mut();
|
||||
if export.ty() != import.ty.ty().func()? {
|
||||
return None;
|
||||
}
|
||||
|
||||
&**(*instance)
|
||||
let entry = instance
|
||||
.export_cache
|
||||
.entry(name.to_string())
|
||||
.or_insert_with(|| {
|
||||
Box::new(wasm_extern_t {
|
||||
which: ExternHost::Func(HostRef::new(export.clone())),
|
||||
})
|
||||
}) as *const wasm_extern_t
|
||||
}
|
||||
None => std::ptr::null_mut(),
|
||||
}
|
||||
});
|
||||
Some(entry)
|
||||
}
|
||||
|
||||
31
crates/c-api/src/wat2wasm.rs
Normal file
31
crates/c-api/src/wat2wasm.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use crate::wasm_byte_vec_t;
|
||||
use std::str;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_wat2wasm(
|
||||
wat: &wasm_byte_vec_t,
|
||||
ret: &mut wasm_byte_vec_t,
|
||||
error: Option<&mut wasm_byte_vec_t>,
|
||||
) -> bool {
|
||||
let wat = match str::from_utf8(wat.as_slice()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => {
|
||||
if let Some(error) = error {
|
||||
error.set_buffer(b"input was not valid utf-8".to_vec());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
match wat::parse_str(wat) {
|
||||
Ok(bytes) => {
|
||||
ret.set_buffer(bytes.into());
|
||||
true
|
||||
}
|
||||
Err(e) => {
|
||||
if let Some(error) = error {
|
||||
error.set_buffer(e.to_string().into_bytes());
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user