diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 054cd14e1..fb95c7dc6 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -95,6 +95,8 @@ pub mod instance; pub mod memory; pub mod module; pub mod table; +#[cfg(all(unix, target_arch = "x86_64"))] +pub mod trampoline; pub mod value; #[allow(non_camel_case_types)] diff --git a/lib/runtime-c-api/src/trampoline.rs b/lib/runtime-c-api/src/trampoline.rs new file mode 100644 index 000000000..e6429f71b --- /dev/null +++ b/lib/runtime-c-api/src/trampoline.rs @@ -0,0 +1,54 @@ +use std::ffi::c_void; +use wasmer_runtime_core::trampoline::*; + +#[repr(C)] +pub struct wasmer_trampoline_buffer_builder_t; + +#[repr(C)] +pub struct wasmer_trampoline_buffer_t; + +#[repr(C)] +pub struct wasmer_trampoline_callable_t; + +#[no_mangle] +pub extern "C" fn wasmer_trampoline_buffer_builder_new() -> *mut wasmer_trampoline_buffer_builder_t +{ + Box::into_raw(Box::new(TrampolineBufferBuilder::new())) as *mut _ +} + +#[no_mangle] +pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_function( + b: *mut wasmer_trampoline_buffer_builder_t, + f: *const wasmer_trampoline_callable_t, + ctx: *const c_void, +) -> usize { + let b = &mut *(b as *mut TrampolineBufferBuilder); + b.add_function(f as *const CallTarget, ctx as *const CallContext) +} + +#[no_mangle] +pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_build( + b: *mut wasmer_trampoline_buffer_builder_t, +) -> *mut wasmer_trampoline_buffer_t { + let b = Box::from_raw(b as *mut TrampolineBufferBuilder); + Box::into_raw(Box::new(b.build())) as *mut _ +} + +#[no_mangle] +pub unsafe extern "C" fn wasmer_trampoline_buffer_destroy(b: *mut wasmer_trampoline_buffer_t) { + Box::from_raw(b); +} + +#[no_mangle] +pub unsafe extern "C" fn wasmer_trampoline_buffer_get_trampoline( + b: *const wasmer_trampoline_buffer_t, + idx: usize, +) -> *const wasmer_trampoline_callable_t { + let b = &*(b as *const TrampolineBuffer); + b.get_trampoline(idx) as _ +} + +#[no_mangle] +pub unsafe extern "C" fn wasmer_trampoline_get_context() -> *mut c_void { + get_context() as *const c_void as *mut c_void +} diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index 92e3e821d..3447fcddd 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -14,8 +14,15 @@ typedef struct { int value; } context_data; +struct print_str_context { + int call_count; +}; + void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) { + struct print_str_context *local_context = wasmer_trampoline_get_context(); + local_context->call_count++; + const wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); uint32_t mem_len = wasmer_memory_length(memory); uint8_t *mem_bytes = wasmer_memory_data(memory); @@ -36,9 +43,22 @@ int main() { wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; wasmer_value_tag returns_sig[] = {}; + struct print_str_context local_context = { + .call_count = 0 + }; + + printf("Creating trampoline buffer\n"); + wasmer_trampoline_buffer_builder_t *tbb = wasmer_trampoline_buffer_builder_new(); + unsigned long print_str_idx = wasmer_trampoline_buffer_builder_add_function( + tbb, + (wasmer_trampoline_callable_t *) print_str, + (void *) &local_context + ); + wasmer_trampoline_buffer_t *tb = wasmer_trampoline_buffer_builder_build(tbb); + const wasmer_trampoline_callable_t *print_str_callable = wasmer_trampoline_buffer_get_trampoline(tb, print_str_idx); printf("Creating new func\n"); - wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str, params_sig, 2, returns_sig, 0); + wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str_callable, params_sig, 2, returns_sig, 0); wasmer_import_t import; char *module_name = "env"; @@ -95,7 +115,10 @@ int main() assert(ptr_len == 13); assert(0 == strcmp(actual_str, "Hello, World!")); assert(context_data_value == actual_context_data_value); + assert(local_context.call_count == 1); + printf("Destroying trampoline buffer\n"); + wasmer_trampoline_buffer_destroy(tb); printf("Destroying func\n"); wasmer_import_func_destroy(func); printf("Destroy instance\n"); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 6752f71a1..1b04b0a73 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -133,6 +133,18 @@ typedef struct { } wasmer_serialized_module_t; +typedef struct { + +} wasmer_trampoline_buffer_builder_t; + +typedef struct { + +} wasmer_trampoline_callable_t; + +typedef struct { + +} wasmer_trampoline_buffer_t; + /** * Creates a new Module from the given wasm bytes. * Returns `wasmer_result_t::WASMER_OK` upon success. @@ -584,6 +596,21 @@ uint32_t wasmer_table_length(wasmer_table_t *table); */ wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); +uintptr_t wasmer_trampoline_buffer_builder_add_function(wasmer_trampoline_buffer_builder_t *b, + const wasmer_trampoline_callable_t *f, + const void *ctx); + +wasmer_trampoline_buffer_t *wasmer_trampoline_buffer_builder_build(wasmer_trampoline_buffer_builder_t *b); + +wasmer_trampoline_buffer_builder_t *wasmer_trampoline_buffer_builder_new(void); + +void wasmer_trampoline_buffer_destroy(wasmer_trampoline_buffer_t *b); + +const wasmer_trampoline_callable_t *wasmer_trampoline_buffer_get_trampoline(const wasmer_trampoline_buffer_t *b, + uintptr_t idx); + +void *wasmer_trampoline_get_context(void); + /** * Returns true for valid wasm bytes and false for invalid bytes */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 99e21fcc8..373ccb074 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -131,6 +131,18 @@ struct wasmer_serialized_module_t { }; +struct wasmer_trampoline_buffer_builder_t { + +}; + +struct wasmer_trampoline_callable_t { + +}; + +struct wasmer_trampoline_buffer_t { + +}; + extern "C" { /// Creates a new Module from the given wasm bytes. @@ -458,6 +470,21 @@ uint32_t wasmer_table_length(wasmer_table_t *table); /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); +uintptr_t wasmer_trampoline_buffer_builder_add_function(wasmer_trampoline_buffer_builder_t *b, + const wasmer_trampoline_callable_t *f, + const void *ctx); + +wasmer_trampoline_buffer_t *wasmer_trampoline_buffer_builder_build(wasmer_trampoline_buffer_builder_t *b); + +wasmer_trampoline_buffer_builder_t *wasmer_trampoline_buffer_builder_new(); + +void wasmer_trampoline_buffer_destroy(wasmer_trampoline_buffer_t *b); + +const wasmer_trampoline_callable_t *wasmer_trampoline_buffer_get_trampoline(const wasmer_trampoline_buffer_t *b, + uintptr_t idx); + +void *wasmer_trampoline_get_context(); + /// Returns true for valid wasm bytes and false for invalid bytes bool wasmer_validate(const uint8_t *wasm_bytes, uint32_t wasm_bytes_len);