diff --git a/CHANGELOG.md b/CHANGELOG.md index aed901cc2..d219b8991 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## **[Unreleased]** +- [#1062](https://github.com/wasmerio/wasmer/pull/1062) Expose some opt-in Emscripten functions to the C API +- [#1032](https://github.com/wasmerio/wasmer/pull/1032) Change the signature of the Emscripten `abort` function to work with Emscripten 1.38.30 - [#1060](https://github.com/wasmerio/wasmer/pull/1060) Test the capi with all the backends - [#1058](https://github.com/wasmerio/wasmer/pull/1058) Fix minor panic issue when `wasmer::compile_with` called with llvm backend. - [#858](https://github.com/wasmerio/wasmer/pull/858) Minor panic fix when wasmer binary with `loader` option run a module without exported `_start` function. diff --git a/Makefile b/Makefile index d0dc4ec1b..40bea0e3a 100644 --- a/Makefile +++ b/Makefile @@ -114,6 +114,10 @@ capi-llvm: cargo build --manifest-path lib/runtime-c-api/Cargo.toml --release \ --no-default-features --features llvm-backend,wasi +capi-emscripten: + cargo build --manifest-path lib/runtime-c-api/Cargo.toml --release \ + --no-default-features --features singlepass-backend,emscripten + # We use cranelift as the default backend for the capi for now capi: capi-cranelift @@ -129,6 +133,10 @@ test-capi-llvm: capi-llvm cargo test --manifest-path lib/runtime-c-api/Cargo.toml --release \ --no-default-features --features llvm-backend,wasi +test-capi-emscripten: capi-emscripten + cargo test --manifest-path lib/runtime-c-api/Cargo.toml --release \ + --no-default-features --features singlepass-backend,emscripten + test-capi: test-capi-singlepass test-capi-cranelift test-capi-llvm capi-test: test-capi diff --git a/lib/runtime-c-api/src/import/emscripten.rs b/lib/runtime-c-api/src/import/emscripten.rs index 7a9b111dd..ca66a630e 100644 --- a/lib/runtime-c-api/src/import/emscripten.rs +++ b/lib/runtime-c-api/src/import/emscripten.rs @@ -4,7 +4,7 @@ use super::*; use crate::{get_slice_checked, instance::wasmer_instance_t, module::wasmer_module_t}; use std::ptr; -use wasmer_emscripten::EmscriptenGlobals; +use wasmer_emscripten::{EmscriptenData, EmscriptenGlobals}; use wasmer_runtime::{Instance, Module}; /// Type used to construct an import_object_t with Emscripten imports. @@ -55,7 +55,14 @@ pub unsafe extern "C" fn wasmer_emscripten_set_up_emscripten( return wasmer_result_t::WASMER_ERROR; } let instance = &mut *(instance as *mut Instance); - instance.context_mut().data = globals as *mut c_void; + let globals = &*(globals as *mut EmscriptenGlobals); + let em_data = Box::into_raw(Box::new(EmscriptenData::new( + instance, + &globals.data, + Default::default(), + ))) as *mut c_void; + instance.context_mut().data = em_data; + match wasmer_emscripten::set_up_emscripten(instance) { Ok(_) => wasmer_result_t::WASMER_OK, Err(e) => { diff --git a/lib/runtime-c-api/src/import/mod.rs b/lib/runtime-c-api/src/import/mod.rs index 978862113..1c3c1521c 100644 --- a/lib/runtime-c-api/src/import/mod.rs +++ b/lib/runtime-c-api/src/import/mod.rs @@ -8,7 +8,7 @@ use crate::{ value::wasmer_value_tag, wasmer_byte_array, wasmer_result_t, }; -use libc::{c_uchar, c_uint}; +use libc::c_uint; use std::{convert::TryFrom, ffi::c_void, ptr, slice, sync::Arc}; use wasmer_runtime::{Global, Memory, Module, Table}; use wasmer_runtime_core::{ diff --git a/lib/runtime-c-api/src/import/wasi.rs b/lib/runtime-c-api/src/import/wasi.rs index 0ff833a61..1dd9d4c15 100644 --- a/lib/runtime-c-api/src/import/wasi.rs +++ b/lib/runtime-c-api/src/import/wasi.rs @@ -1,5 +1,6 @@ use super::*; use crate::get_slice_checked; +use libc::c_uchar; use std::{path::PathBuf, ptr, str}; use wasmer_wasi as wasi; diff --git a/lib/runtime-c-api/tests/test-emscripten-import-object.c b/lib/runtime-c-api/tests/test-emscripten-import-object.c index 03b196f59..51825daef 100644 --- a/lib/runtime-c-api/tests/test-emscripten-import-object.c +++ b/lib/runtime-c-api/tests/test-emscripten-import-object.c @@ -35,95 +35,6 @@ void print_byte_array(wasmer_byte_array *arr) { int main() { - // Create a new func to hold the parameter and signature - // of our `host_print` host function - wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; - wasmer_value_tag returns_sig[] = {}; - wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) host_print, params_sig, 2, returns_sig, 0); - - // Create module name for our imports - // represented in bytes for UTF-8 compatability - const char *module_name = "env"; - wasmer_byte_array module_name_bytes; - module_name_bytes.bytes = (const uint8_t *) module_name; - module_name_bytes.bytes_len = strlen(module_name); - - // Define a function import - const char *import_name = "host_print"; - wasmer_byte_array import_name_bytes; - import_name_bytes.bytes = (const uint8_t *) import_name; - import_name_bytes.bytes_len = strlen(import_name); - wasmer_import_t func_import; - func_import.module_name = module_name_bytes; - func_import.import_name = import_name_bytes; - func_import.tag = WASM_FUNCTION; - func_import.value.func = func; - - // Define a memory import - const char *import_memory_name = "memory"; - wasmer_byte_array import_memory_name_bytes; - import_memory_name_bytes.bytes = (const uint8_t *) import_memory_name; - import_memory_name_bytes.bytes_len = strlen(import_memory_name); - wasmer_import_t memory_import; - memory_import.module_name = module_name_bytes; - memory_import.import_name = import_memory_name_bytes; - memory_import.tag = WASM_MEMORY; - wasmer_memory_t *memory = NULL; - wasmer_limits_t descriptor; - descriptor.min = 256; - wasmer_limit_option_t max; - max.has_some = true; - max.some = 256; - descriptor.max = max; - wasmer_result_t memory_result = wasmer_memory_new(&memory, descriptor); - if (memory_result != WASMER_OK) - { - print_wasmer_error(); - } - memory_import.value.memory = memory; - - // Define a global import - const char *import_global_name = "__memory_base"; - wasmer_byte_array import_global_name_bytes; - import_global_name_bytes.bytes = (const uint8_t *) import_global_name; - import_global_name_bytes.bytes_len = strlen(import_global_name); - wasmer_import_t global_import; - global_import.module_name = module_name_bytes; - global_import.import_name = import_global_name_bytes; - global_import.tag = WASM_GLOBAL; - wasmer_value_t val; - val.tag = WASM_I32; - val.value.I32 = 1024; - wasmer_global_t *global = wasmer_global_new(val, false); - global_import.value.global = global; - - // Define a table import - const char *import_table_name = "table"; - wasmer_byte_array import_table_name_bytes; - import_table_name_bytes.bytes = (const uint8_t *) import_table_name; - import_table_name_bytes.bytes_len = strlen(import_table_name); - wasmer_import_t table_import; - table_import.module_name = module_name_bytes; - table_import.import_name = import_table_name_bytes; - table_import.tag = WASM_TABLE; - wasmer_table_t *table = NULL; - wasmer_limits_t table_descriptor; - table_descriptor.min = 256; - wasmer_limit_option_t table_max; - table_max.has_some = true; - table_max.some = 256; - table_descriptor.max = table_max; - wasmer_result_t table_result = wasmer_table_new(&table, table_descriptor); - if (table_result != WASMER_OK) - { - print_wasmer_error(); - } - table_import.value.table = table; - - - // Create arbitrary arguments for our program - - // Read the Wasm file bytes. FILE *file = fopen("assets/emscripten_hello_world.wasm", "r"); assert(file); @@ -159,11 +70,6 @@ int main() wasmer_import_object_t *import_object = wasmer_emscripten_generate_import_object(emscripten_globals); - // Create our imports - wasmer_import_t imports[] = {func_import, global_import, memory_import, table_import}; - int imports_len = sizeof(imports) / sizeof(imports[0]); - // Add our imports to the import object - wasmer_import_object_extend(import_object, imports, imports_len); // Instantiatoe the module with our import_object wasmer_instance_t *instance = NULL; @@ -178,11 +84,13 @@ int main() // Set up emscripten to be called wasmer_result_t setup_result = wasmer_emscripten_set_up_emscripten(instance, emscripten_globals); + printf("Set up result: %d\n", setup_result); if (setup_result != WASMER_OK) { print_wasmer_error(); } + assert(setup_result == WASMER_OK); const char *emscripten_prog_name = "emscripten_test_program"; @@ -200,7 +108,6 @@ int main() printf("Main result: %d\n", main_result); assert(main_result == WASMER_OK); - wasmer_import_object_iter_t *func_iter = wasmer_import_object_iterate_functions(import_object); puts("Functions in import object:"); @@ -222,10 +129,6 @@ int main() // Use *_destroy methods to cleanup as specified in the header documentation wasmer_emscripten_destroy_emscripten_globals(emscripten_globals); - wasmer_import_func_destroy(func); - wasmer_global_destroy(global); - wasmer_memory_destroy(memory); - wasmer_table_destroy(table); wasmer_instance_destroy(instance); wasmer_import_object_destroy(import_object); wasmer_module_destroy(module);