You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
9.1 KiB

// WebAssembly C API extension for Wasmtime
#ifndef WASMTIME_API_H
#define WASMTIME_API_H
#include <wasm.h>
#include <wasi.h>
#ifdef __cplusplus
extern "C" {
#endif
#define own
#define WASMTIME_DECLARE_OWN(name) \
typedef struct wasmtime_##name##_t wasmtime_##name##_t; \
\
WASM_API_EXTERN void wasmtime_##name##_delete(own wasmtime_##name##_t*);
WASMTIME_DECLARE_OWN(error)
WASM_API_EXTERN void wasmtime_error_message(
const wasmtime_error_t *error,
own wasm_name_t *message
);
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,
};
typedef uint8_t wasmtime_profiling_strategy_t;
enum wasmtime_profiling_strategy_t { // ProfilingStrategy
WASMTIME_PROFILING_STRATEGY_NONE,
WASMTIME_PROFILING_STRATEGY_JITDUMP,
WASMTIME_PROFILING_STRATEGY_VTUNE,
};
Refactor and fill out wasmtime&#39;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&#39;d take `&amp;wasm_foo_t`. Instead of returning `*mut wasm_foo_t` we&#39;d return `Box&lt;wasm_foo_t&gt;`. No ABI/API changes are intended from this commit, it&#39;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.
5 years ago
#define WASMTIME_CONFIG_PROP(ret, name, ty) \
WASM_API_EXTERN ret wasmtime_config_##name##_set(wasm_config_t*, ty);
WASMTIME_CONFIG_PROP(void, debug_info, bool)
Implement interrupting wasm code, reimplement stack overflow (#1490) * Implement interrupting wasm code, reimplement stack overflow This commit is a relatively large change for wasmtime with two main goals: * Primarily this enables interrupting executing wasm code with a trap, preventing infinite loops in wasm code. Note that resumption of the wasm code is not a goal of this commit. * Additionally this commit reimplements how we handle stack overflow to ensure that host functions always have a reasonable amount of stack to run on. This fixes an issue where we might longjmp out of a host function, skipping destructors. Lots of various odds and ends end up falling out in this commit once the two goals above were implemented. The strategy for implementing this was also lifted from Spidermonkey and existing functionality inside of Cranelift. I&#39;ve tried to write up thorough documentation of how this all works in `crates/environ/src/cranelift.rs` where gnarly-ish bits are. A brief summary of how this works is that each function and each loop header now checks to see if they&#39;re interrupted. Interrupts and the stack overflow check are actually folded into one now, where function headers check to see if they&#39;ve run out of stack and the sentinel value used to indicate an interrupt, checked in loop headers, tricks functions into thinking they&#39;re out of stack. An interrupt is basically just writing a value to a location which is read by JIT code. When interrupts are delivered and what triggers them has been left up to embedders of the `wasmtime` crate. The `wasmtime::Store` type has a method to acquire an `InterruptHandle`, where `InterruptHandle` is a `Send` and `Sync` type which can travel to other threads (or perhaps even a signal handler) to get notified from. It&#39;s intended that this provides a good degree of flexibility when interrupting wasm code. Note though that this does have a large caveat where interrupts don&#39;t work when you&#39;re interrupting host code, so if you&#39;ve got a host import blocking for a long time an interrupt won&#39;t actually be received until the wasm starts running again. Some fallout included from this change is: * Unix signal handlers are no longer registered with `SA_ONSTACK`. Instead they run on the native stack the thread was already using. This is possible since stack overflow isn&#39;t handled by hitting the guard page, but rather it&#39;s explicitly checked for in wasm now. Native stack overflow will continue to abort the process as usual. * Unix sigaltstack management is now no longer necessary since we don&#39;t use it any more. * Windows no longer has any need to reset guard pages since we no longer try to recover from faults on guard pages. * On all targets probestack intrinsics are disabled since we use a different mechanism for catching stack overflow. * The C API has been updated with interrupts handles. An example has also been added which shows off how to interrupt a module. Closes #139 Closes #860 Closes #900 * Update comment about magical interrupt value * Store stack limit as a global value, not a closure * Run rustfmt * Handle review comments * Add a comment about SA_ONSTACK * Use `usize` for type of `INTERRUPTED` * Parse human-readable durations * Bring back sigaltstack handling Allows libstd to print out stack overflow on failure still. * Add parsing and emission of stack limit-via-preamble * Fix new example for new apis * Fix host segfault test in release mode * Fix new doc example
5 years ago
WASMTIME_CONFIG_PROP(void, interruptable, bool)
WASMTIME_CONFIG_PROP(void, max_wasm_stack, size_t)
Refactor and fill out wasmtime&#39;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&#39;d take `&amp;wasm_foo_t`. Instead of returning `*mut wasm_foo_t` we&#39;d return `Box&lt;wasm_foo_t&gt;`. No ABI/API changes are intended from this commit, it&#39;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.
5 years ago
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(wasmtime_error_t*, strategy, wasmtime_strategy_t)
Refactor and fill out wasmtime&#39;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&#39;d take `&amp;wasm_foo_t`. Instead of returning `*mut wasm_foo_t` we&#39;d return `Box&lt;wasm_foo_t&gt;`. No ABI/API changes are intended from this commit, it&#39;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.
5 years ago
WASMTIME_CONFIG_PROP(void, cranelift_debug_verifier, bool)
WASMTIME_CONFIG_PROP(void, cranelift_opt_level, wasmtime_opt_level_t)
WASMTIME_CONFIG_PROP(wasmtime_error_t*, profiler, wasmtime_profiling_strategy_t)
///////////////////////////////////////////////////////////////////////////////
// Converts from the text format of WebAssembly to to the binary format.
//
// * `wat` - this it the input buffer with the WebAssembly Text Format inside of
// it. This will be parsed and converted to the binary format.
// * `ret` - if the conversion is successful, this byte vector is filled in with
// the WebAssembly binary format.
//
// Returns a non-null error if parsing fails, or returns `NULL`. If parsing
// fails then `ret` isn't touched.
WASM_API_EXTERN own wasmtime_error_t* wasmtime_wat2wasm(
const wasm_byte_vec_t *wat,
own wasm_byte_vec_t *ret
);
///////////////////////////////////////////////////////////////////////////////
//
// wasmtime_linker_t extension type, binding the `Linker` type in the Rust API
WASMTIME_DECLARE_OWN(linker)
WASM_API_EXTERN own wasmtime_linker_t* wasmtime_linker_new(wasm_store_t* store);
WASM_API_EXTERN void wasmtime_linker_allow_shadowing(wasmtime_linker_t* linker, bool allow_shadowing);
WASM_API_EXTERN own wasmtime_error_t* wasmtime_linker_define(
wasmtime_linker_t *linker,
const wasm_name_t *module,
const wasm_name_t *name,
const wasm_extern_t *item
);
WASM_API_EXTERN own wasmtime_error_t* wasmtime_linker_define_wasi(
wasmtime_linker_t *linker,
const wasi_instance_t *instance
);
WASM_API_EXTERN own wasmtime_error_t* wasmtime_linker_define_instance(
wasmtime_linker_t *linker,
const wasm_name_t *name,
const wasm_instance_t *instance
);
WASM_API_EXTERN own wasmtime_error_t* wasmtime_linker_instantiate(
const wasmtime_linker_t *linker,
const wasm_module_t *module,
own wasm_instance_t **instance,
own wasm_trap_t **trap
);
///////////////////////////////////////////////////////////////////////////////
//
// wasmtime_caller_t extension, binding the `Caller` type in the Rust API
typedef struct wasmtime_caller_t wasmtime_caller_t;
typedef own wasm_trap_t* (*wasmtime_func_callback_t)(const wasmtime_caller_t* caller, const wasm_val_t args[], wasm_val_t results[]);
typedef own wasm_trap_t* (*wasmtime_func_callback_with_env_t)(const wasmtime_caller_t* caller, void* env, const wasm_val_t args[], wasm_val_t results[]);
WASM_API_EXTERN own wasm_func_t* wasmtime_func_new(wasm_store_t*, const wasm_functype_t*, wasmtime_func_callback_t callback);
WASM_API_EXTERN own wasm_func_t* wasmtime_func_new_with_env(
wasm_store_t* store,
const wasm_functype_t* type,
wasmtime_func_callback_with_env_t callback,
void* env,
void (*finalizer)(void*)
);
WASM_API_EXTERN own wasm_extern_t* wasmtime_caller_export_get(const wasmtime_caller_t* caller, const wasm_name_t* name);
///////////////////////////////////////////////////////////////////////////////
Implement interrupting wasm code, reimplement stack overflow (#1490) * Implement interrupting wasm code, reimplement stack overflow This commit is a relatively large change for wasmtime with two main goals: * Primarily this enables interrupting executing wasm code with a trap, preventing infinite loops in wasm code. Note that resumption of the wasm code is not a goal of this commit. * Additionally this commit reimplements how we handle stack overflow to ensure that host functions always have a reasonable amount of stack to run on. This fixes an issue where we might longjmp out of a host function, skipping destructors. Lots of various odds and ends end up falling out in this commit once the two goals above were implemented. The strategy for implementing this was also lifted from Spidermonkey and existing functionality inside of Cranelift. I&#39;ve tried to write up thorough documentation of how this all works in `crates/environ/src/cranelift.rs` where gnarly-ish bits are. A brief summary of how this works is that each function and each loop header now checks to see if they&#39;re interrupted. Interrupts and the stack overflow check are actually folded into one now, where function headers check to see if they&#39;ve run out of stack and the sentinel value used to indicate an interrupt, checked in loop headers, tricks functions into thinking they&#39;re out of stack. An interrupt is basically just writing a value to a location which is read by JIT code. When interrupts are delivered and what triggers them has been left up to embedders of the `wasmtime` crate. The `wasmtime::Store` type has a method to acquire an `InterruptHandle`, where `InterruptHandle` is a `Send` and `Sync` type which can travel to other threads (or perhaps even a signal handler) to get notified from. It&#39;s intended that this provides a good degree of flexibility when interrupting wasm code. Note though that this does have a large caveat where interrupts don&#39;t work when you&#39;re interrupting host code, so if you&#39;ve got a host import blocking for a long time an interrupt won&#39;t actually be received until the wasm starts running again. Some fallout included from this change is: * Unix signal handlers are no longer registered with `SA_ONSTACK`. Instead they run on the native stack the thread was already using. This is possible since stack overflow isn&#39;t handled by hitting the guard page, but rather it&#39;s explicitly checked for in wasm now. Native stack overflow will continue to abort the process as usual. * Unix sigaltstack management is now no longer necessary since we don&#39;t use it any more. * Windows no longer has any need to reset guard pages since we no longer try to recover from faults on guard pages. * On all targets probestack intrinsics are disabled since we use a different mechanism for catching stack overflow. * The C API has been updated with interrupts handles. An example has also been added which shows off how to interrupt a module. Closes #139 Closes #860 Closes #900 * Update comment about magical interrupt value * Store stack limit as a global value, not a closure * Run rustfmt * Handle review comments * Add a comment about SA_ONSTACK * Use `usize` for type of `INTERRUPTED` * Parse human-readable durations * Bring back sigaltstack handling Allows libstd to print out stack overflow on failure still. * Add parsing and emission of stack limit-via-preamble * Fix new example for new apis * Fix host segfault test in release mode * Fix new doc example
5 years ago
//
// wasmtime_interrupt_handle_t extension, allowing interruption of running wasm
// modules.
//
// Note that `wasmtime_interrupt_handle_t` is safe to send to other threads and
// interrupt/delete.
//
// Also note that `wasmtime_interrupt_handle_new` may return NULL if interrupts
// are not enabled in `wasm_config_t`.
WASMTIME_DECLARE_OWN(interrupt_handle)
WASM_API_EXTERN own wasmtime_interrupt_handle_t *wasmtime_interrupt_handle_new(wasm_store_t *store);
WASM_API_EXTERN void wasmtime_interrupt_handle_interrupt(wasmtime_interrupt_handle_t *handle);
///////////////////////////////////////////////////////////////////////////////
//
// Extensions to `wasm_frame_t`
WASM_API_EXTERN const wasm_name_t *wasmtime_frame_func_name(const wasm_frame_t*);
WASM_API_EXTERN const wasm_name_t *wasmtime_frame_module_name(const wasm_frame_t*);
///////////////////////////////////////////////////////////////////////////////
//
// Extensions to the C API which augment existing functionality with extra
// error reporting, safety, etc.
// Similar to `wasm_func_call`, but with a few tweaks:
//
// * `args` and `results` have a size parameter saying how big the arrays are
// * An error *and* a trap can be returned
// * Errors are returned if `args` have the wrong types, if the args/results
// arrays have the wrong lengths, or if values come from the wrong store.
//
// The are three possible return states from this function:
//
// 1. The returned error is non-null. This means `results`
// wasn't written to and `trap` will have `NULL` written to it. This state
// means that programmer error happened when calling the function (e.g. the
// size of the args/results were wrong)
// 2. The trap pointer is filled in. This means the returned error is `NULL` and
// `results` was not written to. This state means that the function was
// executing but hit a wasm trap while executing.
// 3. The error and trap returned are both `NULL` and `results` are written to.
// This means that the function call worked and the specified results were
// produced.
//
// The `trap` pointer cannot be `NULL`. The `args` and `results` pointers may be
// `NULL` if the corresponding length is zero.
WASM_API_EXTERN own wasmtime_error_t *wasmtime_func_call(
wasm_func_t *func,
const wasm_val_t *args,
size_t num_args,
wasm_val_t *results,
size_t num_results,
own wasm_trap_t **trap
);
// Similar to `wasm_global_new`, but with a few tweaks:
//
// * An error is returned instead of `wasm_global_t`, which is taken as an
// out-parameter
// * An error happens when the `type` specified does not match the type of the
// value `val`, or if it comes from a different store than `store`.
WASM_API_EXTERN own wasmtime_error_t *wasmtime_global_new(
wasm_store_t *store,
const wasm_globaltype_t *type,
const wasm_val_t *val,
own wasm_global_t **ret
);
// Similar to `wasm_global_set`, but with an error that can be returned if the
// specified value does not come from the same store as this global, if the
// global is immutable, or if the specified value has the wrong type.
WASM_API_EXTERN own wasmtime_error_t *wasmtime_global_set(
wasm_global_t *global,
const wasm_val_t *val
);
// Similar to `wasm_instance_new`, but with tweaks:
//
// * An error message can be returned from this function.
// * The number of imports specified is passed as an argument
// * The `trap` pointer is required to not be NULL.
// * No `wasm_store_t` argument is required.
//
// The states of return values from this function are similar to
// `wasmtime_func_call` where an error can be returned meaning something like a
// link error in this context. A trap can be returned (meaning no error or
// instance is returned), or an instance can be returned (meaning no error or
// trap is returned).
WASM_API_EXTERN own wasmtime_error_t *wasmtime_instance_new(
const wasm_module_t *module,
const wasm_extern_t* const imports[],
size_t num_imports,
own wasm_instance_t **instance,
own wasm_trap_t **trap
);
// Similar to `wasm_module_new`, but an error is returned to return a
// descriptive error message in case compilation fails.
WASM_API_EXTERN own wasmtime_error_t *wasmtime_module_new(
wasm_store_t *store,
const wasm_byte_vec_t *binary,
own wasm_module_t **ret
);
// Similar to `wasm_module_validate`, but an error is returned to return a
// descriptive error message in case compilation fails.
WASM_API_EXTERN own wasmtime_error_t *wasmtime_module_validate(
wasm_store_t *store,
const wasm_byte_vec_t *binary
);
#undef own
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WASMTIME_API_H