Add foundational emscripten functions and types to C API

This commit is contained in:
Mark McCaskey 2019-12-13 13:04:54 -08:00
parent 22dcbcc074
commit f1c95a81ab
7 changed files with 156 additions and 13 deletions

1
Cargo.lock generated
View File

@ -2286,6 +2286,7 @@ version = "0.11.0"
dependencies = [
"cbindgen 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-emscripten 0.11.0",
"wasmer-runtime 0.11.0",
"wasmer-runtime-core 0.11.0",
"wasmer-wasi 0.11.0",

View File

@ -32,6 +32,11 @@ path = "../wasi"
version = "0.11.0"
optional = true
[dependencies.wasmer-emscripten]
path = "../emscripten"
version = "0.11.0"
optional = true
[features]
default = ["cranelift-backend", "wasi"]
debug = ["wasmer-runtime/debug"]
@ -39,6 +44,7 @@ cranelift-backend = ["wasmer-runtime/cranelift", "wasmer-runtime/default-backend
llvm-backend = ["wasmer-runtime/llvm", "wasmer-runtime/default-backend-llvm"]
singlepass-backend = ["wasmer-runtime/singlepass", "wasmer-runtime/default-backend-singlepass"]
wasi = ["wasmer-wasi"]
emscripten = ["wasmer-emscripten"]
[build-dependencies]
cbindgen = "0.9"

View File

@ -12,7 +12,7 @@ fn main() {
let mut out_wasmer_header_file = PathBuf::from(&out_dir);
out_wasmer_header_file.push("wasmer");
const WASMER_PRE_HEADER: &str = r#"
let mut pre_header = r#"
#if !defined(WASMER_H_MACROS)
#define WASMER_H_MACROS
@ -28,17 +28,27 @@ fn main() {
#endif
#endif
#endif // WASMER_H_MACROS
"#;
"#
.to_string();
#[cfg(feature = "emscripten")]
{
pre_header += "#define WASMER_EMSCRIPTEN_ENABLED\n";
}
// close pre header
pre_header += "#endif // WASMER_H_MACROS\n";
// Generate the C bindings in the `OUT_DIR`.
out_wasmer_header_file.set_extension("h");
Builder::new()
.with_crate(crate_dir.clone())
.with_language(Language::C)
.with_include_guard("WASMER_H")
.with_header(WASMER_PRE_HEADER)
.with_header(&pre_header)
.with_define("target_family", "windows", "_WIN32")
.with_define("target_arch", "x86_64", "ARCH_X86_64")
.with_define("feature", "emscripten", "WASMER_EMSCRIPTEN_ENABLED")
.generate()
.expect("Unable to generate C bindings")
.write_to_file(out_wasmer_header_file.as_path());
@ -49,9 +59,10 @@ fn main() {
.with_crate(crate_dir)
.with_language(Language::Cxx)
.with_include_guard("WASMER_H")
.with_header(WASMER_PRE_HEADER)
.with_header(&pre_header)
.with_define("target_family", "windows", "_WIN32")
.with_define("target_arch", "x86_64", "ARCH_X86_64")
.with_define("feature", "emscripten", "WASMER_EMSCRIPTEN_ENABLED")
.generate()
.expect("Unable to generate C++ bindings")
.write_to_file(out_wasmer_header_file.as_path());

View File

@ -0,0 +1,58 @@
//! Functions and types for dealing with Emscripten imports
use super::*;
use crate::module::wasmer_module_t;
use std::ptr;
use wasmer_emscripten::EmscriptenGlobals;
use wasmer_runtime::Module;
/// Type used to construct an import_object_t with Emscripten imports.
#[repr(C)]
pub struct wasmer_emscripten_globals_t;
/// Create a `wasmer_emscripten_globals_t` from a Wasm module.
#[no_mangle]
pub unsafe extern "C" fn wasmer_emscripten_get_emscripten_globals(
module: *const wasmer_module_t,
) -> *mut wasmer_emscripten_globals_t {
if module.is_null() {
return ptr::null_mut();
}
let module = &*(module as *const Module);
match EmscriptenGlobals::new(module) {
Ok(globals) => Box::into_raw(Box::new(globals)) as *mut wasmer_emscripten_globals_t,
Err(msg) => {
update_last_error(CApiError { msg });
return ptr::null_mut();
}
}
}
/// Destroy `wasmer_emscrpten_globals_t` created by
/// `wasmer_emscripten_get_emscripten_globals`.
#[no_mangle]
pub unsafe extern "C" fn wasmer_emscripten_destroy_emscripten_globals(
globals: *mut wasmer_emscripten_globals_t,
) {
if globals.is_null() {
return;
}
let _ = Box::from_raw(globals);
}
/// Create a `wasmer_import_object_t` with Emscripten imports, use
/// `wasmer_emscripten_get_emscripten_globals` to get a
/// `wasmer_emscripten_globals_t` from a `wasmer_module_t`.
#[no_mangle]
pub unsafe extern "C" fn wasmer_emscripten_generate_import_object(
globals: *mut wasmer_emscripten_globals_t,
) -> *mut wasmer_import_object_t {
if globals.is_null() {
return ptr::null_mut();
}
// TODO: figure out if we should be using UnsafeCell here or something
let g = &mut *(globals as *mut EmscriptenGlobals);
let import_object = Box::new(wasmer_emscripten::generate_emscripten_env(g));
Box::into_raw(import_object) as *mut wasmer_import_object_t
}

View File

@ -61,6 +61,12 @@ mod wasi;
#[cfg(feature = "wasi")]
pub use self::wasi::*;
#[cfg(feature = "emscripten")]
mod emscripten;
#[cfg(feature = "emscripten")]
pub use self::emscripten::*;
/// Gets an entry from an ImportObject at the name and namespace.
/// Stores `name`, `namespace`, and `import_export_value` in `import`.
/// Thus these must remain valid for the lifetime of `import`.
@ -437,6 +443,9 @@ pub unsafe extern "C" fn wasmer_import_descriptors(
module: *const wasmer_module_t,
import_descriptors: *mut *mut wasmer_import_descriptors_t,
) {
if module.is_null() {
return;
}
let module = &*(module as *const Module);
let total_imports = module.info().imported_functions.len()
+ module.info().imported_tables.len()

View File

@ -74,6 +74,19 @@ typedef struct {
} wasmer_module_t;
#if defined(WASMER_EMSCRIPTEN_ENABLED)
/**
* Type used to construct an import_object_t with Emscripten imports.
*/
typedef struct {
} wasmer_emscripten_globals_t;
#endif
typedef struct {
} wasmer_import_object_t;
/**
* Opaque pointer to `NamedExportDescriptor`.
*/
@ -153,10 +166,6 @@ typedef struct {
typedef struct {
} wasmer_import_object_t;
typedef struct {
} wasmer_table_t;
/**
@ -247,6 +256,30 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module,
uint8_t *wasm_bytes,
uint32_t wasm_bytes_len);
#if defined(WASMER_EMSCRIPTEN_ENABLED)
/**
* Destroy `wasmer_emscrpten_globals_t` created by
* `wasmer_emscripten_get_emscripten_globals`.
*/
void wasmer_emscripten_destroy_emscripten_globals(wasmer_emscripten_globals_t *globals);
#endif
#if defined(WASMER_EMSCRIPTEN_ENABLED)
/**
* Create a `wasmer_import_object_t` with Emscripten imports, use
* `wasmer_emscripten_get_emscripten_globals` to get a
* `wasmer_emscripten_globals_t` from a `wasmer_module_t`.
*/
wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscripten_globals_t *globals);
#endif
#if defined(WASMER_EMSCRIPTEN_ENABLED)
/**
* Create a `wasmer_emscripten_globals_t` from a Wasm module.
*/
wasmer_emscripten_globals_t *wasmer_emscripten_get_emscripten_globals(const wasmer_module_t *module);
#endif
/**
* Gets export descriptor kind
*/

View File

@ -61,6 +61,17 @@ struct wasmer_module_t {
};
#if defined(WASMER_EMSCRIPTEN_ENABLED)
/// Type used to construct an import_object_t with Emscripten imports.
struct wasmer_emscripten_globals_t {
};
#endif
struct wasmer_import_object_t {
};
/// Opaque pointer to `NamedExportDescriptor`.
struct wasmer_export_descriptor_t {
@ -128,10 +139,6 @@ struct wasmer_import_func_t {
};
struct wasmer_import_object_t {
};
struct wasmer_table_t {
};
@ -216,6 +223,24 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module,
uint8_t *wasm_bytes,
uint32_t wasm_bytes_len);
#if defined(WASMER_EMSCRIPTEN_ENABLED)
/// Destroy `wasmer_emscrpten_globals_t` created by
/// `wasmer_emscripten_get_emscripten_globals`.
void wasmer_emscripten_destroy_emscripten_globals(wasmer_emscripten_globals_t *globals);
#endif
#if defined(WASMER_EMSCRIPTEN_ENABLED)
/// Create a `wasmer_import_object_t` with Emscripten imports, use
/// `wasmer_emscripten_get_emscripten_globals` to get a
/// `wasmer_emscripten_globals_t` from a `wasmer_module_t`.
wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscripten_globals_t *globals);
#endif
#if defined(WASMER_EMSCRIPTEN_ENABLED)
/// Create a `wasmer_emscripten_globals_t` from a Wasm module.
wasmer_emscripten_globals_t *wasmer_emscripten_get_emscripten_globals(const wasmer_module_t *module);
#endif
/// Gets export descriptor kind
wasmer_import_export_kind wasmer_export_descriptor_kind(wasmer_export_descriptor_t *export_);