diff options
Diffstat (limited to 'wasm2c')
-rw-r--r-- | wasm2c/examples/fac/fac.c | 11 | ||||
-rw-r--r-- | wasm2c/wasm-rt-impl.c | 53 | ||||
-rw-r--r-- | wasm2c/wasm-rt-impl.h | 8 | ||||
-rw-r--r-- | wasm2c/wasm-rt.h | 54 |
4 files changed, 118 insertions, 8 deletions
diff --git a/wasm2c/examples/fac/fac.c b/wasm2c/examples/fac/fac.c index 106d7768..05b93cd8 100644 --- a/wasm2c/examples/fac/fac.c +++ b/wasm2c/examples/fac/fac.c @@ -1,6 +1,12 @@ /* Automatically generated by wasm2c */ #include <math.h> #include <string.h> +#if defined(_MSC_VER) +#include <intrin.h> +#include <malloc.h> +#else +#include <alloca.h> +#endif #include "fac.h" @@ -127,7 +133,7 @@ DEFINE_STORE(i64_store32, u32, u64) #if defined(_MSC_VER) -#include <intrin.h> +#define alloca _alloca // Adapted from // https://github.com/nemequ/portable-snippets/blob/master/builtin/builtin.h @@ -453,6 +459,8 @@ static u32 func_types[1]; static void init_func_types(void) { func_types[0] = wasm_rt_register_func_type(1, 1, WASM_RT_I32, WASM_RT_I32); } +static void init_tags(void) { +} static u32 w2c_fac(u32); @@ -496,6 +504,7 @@ static void init_exports(void) { void Z_fac_init(void) { init_func_types(); + init_tags(); init_globals(); init_memory(); init_table(); diff --git a/wasm2c/wasm-rt-impl.c b/wasm2c/wasm-rt-impl.c index 885a58a2..96b3b395 100644 --- a/wasm2c/wasm-rt-impl.c +++ b/wasm2c/wasm-rt-impl.c @@ -37,6 +37,7 @@ #endif #define PAGE_SIZE 65536 +#define MAX_EXCEPTION_SIZE PAGE_SIZE typedef struct FuncType { wasm_rt_type_t* params; @@ -58,6 +59,12 @@ static uint32_t g_func_type_count; jmp_buf wasm_rt_jmp_buf; +static uint32_t g_active_exception_tag; +static uint8_t g_active_exception[MAX_EXCEPTION_SIZE]; +static uint32_t g_active_exception_size; + +static jmp_buf* g_unwind_target; + void wasm_rt_trap(wasm_rt_trap_t code) { assert(code != WASM_RT_TRAP_NONE); #if !WASM_RT_MEMCHECK_SIGNAL_HANDLER @@ -112,6 +119,50 @@ uint32_t wasm_rt_register_func_type(uint32_t param_count, return idx + 1; } +uint32_t wasm_rt_register_tag(uint32_t size) { + static uint32_t s_tag_count = 0; + + if (size > MAX_EXCEPTION_SIZE) { + wasm_rt_trap(WASM_RT_TRAP_EXHAUSTION); + } + return s_tag_count++; +} + +void wasm_rt_load_exception(uint32_t tag, uint32_t size, const void* values) { + assert(size <= MAX_EXCEPTION_SIZE); + + g_active_exception_tag = tag; + g_active_exception_size = size; + + if (size) { + memcpy(g_active_exception, values, size); + } +} + +WASM_RT_NO_RETURN void wasm_rt_throw(void) { + WASM_RT_LONGJMP(*g_unwind_target, WASM_RT_TRAP_UNCAUGHT_EXCEPTION); +} + +jmp_buf* wasm_rt_get_unwind_target(void) { + return g_unwind_target; +} + +void wasm_rt_set_unwind_target(jmp_buf* target) { + g_unwind_target = target; +} + +uint32_t wasm_rt_exception_tag(void) { + return g_active_exception_tag; +} + +uint32_t wasm_rt_exception_size(void) { + return g_active_exception_size; +} + +void* wasm_rt_exception(void) { + return g_active_exception; +} + #if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX static void signal_handler(int sig, siginfo_t* si, void* unused) { if (si->si_code == SEGV_ACCERR) { @@ -325,6 +376,8 @@ const char* wasm_rt_strerror(wasm_rt_trap_t trap) { return "Unreachable instruction executed"; case WASM_RT_TRAP_CALL_INDIRECT: return "Invalid call_indirect"; + case WASM_RT_TRAP_UNCAUGHT_EXCEPTION: + return "Uncaught exception"; } return "invalid trap code"; } diff --git a/wasm2c/wasm-rt-impl.h b/wasm2c/wasm-rt-impl.h index c275bbf6..c11c80b9 100644 --- a/wasm2c/wasm-rt-impl.h +++ b/wasm2c/wasm-rt-impl.h @@ -17,8 +17,6 @@ #ifndef WASM_RT_IMPL_H_ #define WASM_RT_IMPL_H_ -#include <setjmp.h> - #include "wasm-rt.h" #ifdef __cplusplus @@ -29,10 +27,8 @@ extern "C" { extern jmp_buf wasm_rt_jmp_buf; #if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX -#define WASM_RT_SETJMP(buf) sigsetjmp(buf, 1) #define WASM_RT_LONGJMP(buf, val) siglongjmp(buf, val) #else -#define WASM_RT_SETJMP(buf) setjmp(buf) #define WASM_RT_LONGJMP(buf, val) longjmp(buf, val) /** Saved call stack depth that will be restored in case a trap occurs. */ extern uint32_t wasm_rt_saved_call_stack_depth; @@ -55,10 +51,12 @@ extern uint32_t wasm_rt_saved_call_stack_depth; * ``` */ #if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX -#define wasm_rt_impl_try() WASM_RT_SETJMP(wasm_rt_jmp_buf) +#define wasm_rt_impl_try() \ + (wasm_rt_set_unwind_target(&wasm_rt_jmp_buf), WASM_RT_SETJMP(wasm_rt_jmp_buf)) #else #define wasm_rt_impl_try() \ (wasm_rt_saved_call_stack_depth = wasm_rt_call_stack_depth, \ + wasm_rt_set_unwind_target(&wasm_rt_jmp_buf), \ WASM_RT_SETJMP(wasm_rt_jmp_buf)) #endif diff --git a/wasm2c/wasm-rt.h b/wasm2c/wasm-rt.h index fed82a27..fd895453 100644 --- a/wasm2c/wasm-rt.h +++ b/wasm2c/wasm-rt.h @@ -17,6 +17,7 @@ #ifndef WASM_RT_H_ #define WASM_RT_H_ +#include <setjmp.h> #include <stdbool.h> #include <stdint.h> #include <string.h> @@ -115,6 +116,7 @@ typedef enum { WASM_RT_TRAP_INVALID_CONVERSION, /** Conversion from NaN to integer. */ WASM_RT_TRAP_UNREACHABLE, /** Unreachable instruction executed. */ WASM_RT_TRAP_CALL_INDIRECT, /** Invalid call_indirect, for any reason. */ + WASM_RT_TRAP_UNCAUGHT_EXCEPTION, /* Exception thrown and not caught */ #if WASM_RT_MERGED_OOB_AND_EXHAUSTION_TRAPS WASM_RT_TRAP_EXHAUSTION = WASM_RT_TRAP_OOB, #else @@ -175,8 +177,8 @@ void wasm_rt_init(void); void wasm_rt_free(void); /** - * Stop execution immediately and jump back to the call to `wasm_rt_try`. - * The result of `wasm_rt_try` will be the provided trap reason. + * Stop execution immediately and jump back to the call to `wasm_rt_impl_try`. + * The result of `wasm_rt_impl_try` will be the provided trap reason. * * This is typically called by the generated code, and not the embedder. */ @@ -210,6 +212,54 @@ const char* wasm_rt_strerror(wasm_rt_trap_t trap); uint32_t wasm_rt_register_func_type(uint32_t params, uint32_t results, ...); /** + * Register a tag with the given size. Returns the tag. + */ +uint32_t wasm_rt_register_tag(uint32_t size); + +/** + * Set the active exception to given tag, size, and contents. + */ +void wasm_rt_load_exception(uint32_t tag, uint32_t size, const void* values); + +/** + * Throw the active exception. + */ +WASM_RT_NO_RETURN void wasm_rt_throw(void); + +/** + * Get the current unwind target if an exception is thrown. + */ +jmp_buf* wasm_rt_get_unwind_target(void); + +/** + * Set the unwind target if an exception is thrown. + */ +void wasm_rt_set_unwind_target(jmp_buf* target); + +/** + * Tag of the active exception. + */ +uint32_t wasm_rt_exception_tag(void); + +/** + * Size of the active exception. + */ +uint32_t wasm_rt_exception_size(void); + +/** + * Contents of the active exception. + */ +void* wasm_rt_exception(void); + +#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX +#define WASM_RT_SETJMP(buf) sigsetjmp(buf, 1) +#else +#define WASM_RT_SETJMP(buf) setjmp(buf) +#endif + +#define wasm_rt_try(target) WASM_RT_SETJMP(target) + +/** * Initialize a Memory object with an initial page size of `initial_pages` and * a maximum page size of `max_pages`. * |