From 961853fd1c96f106e580c44b3e5de1b9f74c0160 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 5 Feb 2020 09:29:46 -0600 Subject: [PATCH] Implement wasm_config_new and wasm_engine_new_with_config (#901) * Implement wasm_config_new and wasm_engine_new_with_config --- crates/c-api/examples/Makefile | 16 +++++ crates/c-api/examples/config-debug.c | 99 +++++++++++++++++++++++++++ crates/c-api/examples/fib-wasm.c | 13 ++++ crates/c-api/examples/fib-wasm.wasm | Bin 0 -> 972 bytes crates/c-api/include/wasmtime.h | 45 ++++++++++++ crates/c-api/src/ext.rs | 88 ++++++++++++++++++++++++ crates/c-api/src/lib.rs | 29 ++++++-- 7 files changed, 286 insertions(+), 4 deletions(-) create mode 100644 crates/c-api/examples/config-debug.c create mode 100644 crates/c-api/examples/fib-wasm.c create mode 100755 crates/c-api/examples/fib-wasm.wasm create mode 100644 crates/c-api/include/wasmtime.h create mode 100644 crates/c-api/src/ext.rs diff --git a/crates/c-api/examples/Makefile b/crates/c-api/examples/Makefile index a9310949c3..b309e80484 100644 --- a/crates/c-api/examples/Makefile +++ b/crates/c-api/examples/Makefile @@ -153,3 +153,19 @@ CARGO_RUN: clean: rm -rf ${OUT_DIR} +############################################################################### +# Other examples + +WASM_EXT_INCLUDE = ${WASMTIME_API_DIR}/include + +run-config-debug-c: ${EXAMPLE_OUT}/config-debug-c ${EXAMPLE_OUT}/fib-wasm.wasm + @echo ==== C config ====; \ + cd ${EXAMPLE_OUT}; ./config-debug-c + @echo ==== Done ==== + +${EXAMPLE_OUT}/fib-wasm.wasm: fib-wasm.wasm + cp $< $@ + +${EXAMPLE_OUT}/config-debug-c.o: config-debug.c ${WASM_INCLUDE}/wasm.h ${WASM_EXT_INCLUDE}/wasmtime.h + mkdir -p ${EXAMPLE_OUT} + ${C_COMP} -c ${C_FLAGS} -I. -I${WASM_INCLUDE} -I${WASM_EXT_INCLUDE} $< -o $@ diff --git a/crates/c-api/examples/config-debug.c b/crates/c-api/examples/config-debug.c new file mode 100644 index 0000000000..650d9645c9 --- /dev/null +++ b/crates/c-api/examples/config-debug.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include + +#include +#include "wasmtime.h" + +#define own + +int main(int argc, const char* argv[]) { + // Configuring engine to support generating of DWARF info. + // lldb can be used to attach to the program and observe + // original fib-wasm.c source code and variables. + wasm_config_t* config = wasm_config_new(); + wasmtime_config_debug_info_set(config, true); + + // Initialize. + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new_with_config(config); + wasm_store_t* store = wasm_store_new(engine); + + // Load binary. + printf("Loading binary...\n"); + FILE* file = fopen("fib-wasm.wasm", "r"); + if (!file) { + printf("> Error loading module!\n"); + return 1; + } + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + wasm_byte_vec_t binary; + wasm_byte_vec_new_uninitialized(&binary, file_size); + if (fread(binary.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + return 1; + } + fclose(file); + + // Compile. + printf("Compiling module...\n"); + own wasm_module_t* module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + return 1; + } + + wasm_byte_vec_delete(&binary); + + // Instantiate. + printf("Instantiating module...\n"); + own wasm_instance_t* instance = + wasm_instance_new(store, module, NULL, NULL); + if (!instance) { + printf("> Error instantiating module!\n"); + return 1; + } + + // Extract export. + printf("Extracting export...\n"); + own wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + if (exports.size == 0) { + printf("> Error accessing exports!\n"); + return 1; + } + // Getting second export (first is memory). + const wasm_func_t* run_func = wasm_extern_as_func(exports.data[1]); + if (run_func == NULL) { + printf("> Error accessing export!\n"); + return 1; + } + + wasm_module_delete(module); + wasm_instance_delete(instance); + + // Call. + printf("Calling fib...\n"); + wasm_val_t params[1] = { {.kind = WASM_I32, .of = {.i32 = 6}} }; + wasm_val_t results[1]; + if (wasm_func_call(run_func, params, results)) { + printf("> Error calling function!\n"); + return 1; + } + + wasm_extern_vec_delete(&exports); + + printf("> fib(6) = %d\n", results[0].of.i32); + + // Shut down. + printf("Shutting down...\n"); + wasm_store_delete(store); + wasm_engine_delete(engine); + + // All done. + printf("Done.\n"); + return 0; +} diff --git a/crates/c-api/examples/fib-wasm.c b/crates/c-api/examples/fib-wasm.c new file mode 100644 index 0000000000..20c06f5efa --- /dev/null +++ b/crates/c-api/examples/fib-wasm.c @@ -0,0 +1,13 @@ +// Compile with: +// clang --target=wasm32 fib-wasm.c -o fib-wasm.wasm -g \ +// -Wl,--no-entry,--export=fib -nostdlib -fdebug-prefix-map=$PWD=. + +int fib(int n) { + int i, t, a = 0, b = 1; + for (i = 0; i < n; i++) { + t = a; + a = b; + b += t; + } + return b; +} diff --git a/crates/c-api/examples/fib-wasm.wasm b/crates/c-api/examples/fib-wasm.wasm new file mode 100755 index 0000000000000000000000000000000000000000..0a1ebac4293d8d930487c9d325c5bcc2aec9250d GIT binary patch literal 972 zcmcIj&2G~`5T4!jIzRr&k5ih89(E}e(-=$dooBd$#o&t;oWhEQ+Ei9LN&JO0#;ZNEx?tL|Hfo5_3hxqg4|OW1g`f777M@ zA%@$Df=TaLoOFk0crO|nj_QiQgjhNJQZ$BkfkyvMw4cDfPLUz}y^7QG<+oQzqvzEV zg>)4|R5`tlitnx?^TQPa{u<{TWdzoxG(QMN(Ug?Ps_k%Q7Z-2ZB~sQ=iHl@e->oux z$GB(QS=w_RETIq%^pe_hu=eIZklzMo-!}{c%fP3r^Y`NeDf~ksRqtcs$nhoO!AjU9;c(Q?r?OnyWY|ge-Pn&nZJTFlEXTkNr=j5R*9VWy@;@ftrnOV38V2i>Z}Jx MgwKxf^#4i!0}v;#x&QzG literal 0 HcmV?d00001 diff --git a/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h new file mode 100644 index 0000000000..16b463bb5a --- /dev/null +++ b/crates/c-api/include/wasmtime.h @@ -0,0 +1,45 @@ +// WebAssembly C API extension for Wasmtime + +#ifndef WASMTIME_API_H +#define WASMTIME_API_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t wasmtime_strategy_t; +enum wasmtime_strategy_enum { // Strategy + WASMTIME_STRATEGY_AUTO, + WASMTIME_STRATEGY_CRANELIFT, + WASMTIME_STRATEGY_LIGHTBEAM, +}; + +typedef uint8_t wasmtime_opt_level_t; +enum wasmtime_opt_level_enum { // OptLevel + WASMTIME_OPT_LEVEL_NONE, + WASMTIME_OPT_LEVEL_SPEED, + WASMTIME_OPT_LEVEL_SPEED_AND_SIZE, +}; + +#define WASMTIME_CONFIG_PROP(name, ty) \ + WASM_API_EXTERN void 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) + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WASMTIME_API_H diff --git a/crates/c-api/src/ext.rs b/crates/c-api/src/ext.rs new file mode 100644 index 0000000000..549bb1e604 --- /dev/null +++ b/crates/c-api/src/ext.rs @@ -0,0 +1,88 @@ +//! This file defines the extern "C" API extension, which are specific +//! to the wasmtime implementation. + +use crate::wasm_config_t; +use wasmtime::{OptLevel, Strategy}; + +#[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, +} + +#[no_mangle] +pub unsafe extern "C" fn wasmtime_config_debug_info_set(c: *mut wasm_config_t, enable: bool) { + (*c).config.debug_info(enable); +} + +#[no_mangle] +pub unsafe extern "C" fn wasmtime_config_wasm_threads_set(c: *mut wasm_config_t, enable: bool) { + (*c).config.wasm_threads(enable); +} + +#[no_mangle] +pub unsafe 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 unsafe extern "C" fn wasmtime_config_wasm_simd_set(c: *mut wasm_config_t, enable: bool) { + (*c).config.wasm_simd(enable); +} + +#[no_mangle] +pub unsafe 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 unsafe 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 unsafe extern "C" fn wasmtime_config_strategy_set( + c: *mut wasm_config_t, + strategy: wasmtime_strategy_t, +) { + use wasmtime_strategy_t::*; + drop((*c).config.strategy(match strategy { + WASMTIME_STRATEGY_AUTO => Strategy::Auto, + WASMTIME_STRATEGY_CRANELIFT => Strategy::Cranelift, + WASMTIME_STRATEGY_LIGHTBEAM => Strategy::Lightbeam, + })); +} + +#[no_mangle] +pub unsafe 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 unsafe 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, + }); +} diff --git a/crates/c-api/src/lib.rs b/crates/c-api/src/lib.rs index 877510652a..24490384ad 100644 --- a/crates/c-api/src/lib.rs +++ b/crates/c-api/src/lib.rs @@ -10,9 +10,9 @@ use std::panic::{self, AssertUnwindSafe}; use std::rc::Rc; use std::{mem, ptr, slice}; use wasmtime::{ - AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType, - HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table, - TableType, Trap, Val, ValType, + AnyRef, Callable, Config, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, + GlobalType, HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, + Table, TableType, Trap, Val, ValType, }; macro_rules! declare_vec { @@ -159,7 +159,7 @@ pub type wasm_name_t = wasm_byte_vec_t; #[repr(C)] #[derive(Clone)] pub struct wasm_config_t { - _unused: [u8; 0], + pub(crate) config: Config, } #[repr(C)] #[derive(Clone)] @@ -451,6 +451,14 @@ pub unsafe extern "C" fn wasm_engine_delete(engine: *mut wasm_engine_t) { let _ = Box::from_raw(engine); } +#[no_mangle] +pub unsafe extern "C" fn wasm_config_new() -> *mut wasm_config_t { + let config = Box::new(wasm_config_t { + config: Config::default(), + }); + Box::into_raw(config) +} + #[no_mangle] pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t { let engine = Box::new(wasm_engine_t { @@ -459,6 +467,15 @@ pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t { Box::into_raw(engine) } +#[no_mangle] +pub unsafe extern "C" fn wasm_engine_new_with_config(c: *mut wasm_config_t) -> *mut wasm_engine_t { + let config = Box::from_raw(c).config; + let engine = Box::new(wasm_engine_t { + engine: HostRef::new(Engine::new(&config)), + }); + Box::into_raw(engine) +} + #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t { match &(*e).which { @@ -1745,3 +1762,7 @@ pub unsafe extern "C" fn wasm_valtype_vec_copy( let slice = slice::from_raw_parts((*src).data, (*src).size); (*out).set_from_slice(slice); } + +mod ext; + +pub use crate::ext::*;