summaryrefslogtreecommitdiff
path: root/wasm2c
diff options
context:
space:
mode:
Diffstat (limited to 'wasm2c')
-rw-r--r--wasm2c/examples/fac/fac.c11
-rw-r--r--wasm2c/wasm-rt-impl.c53
-rw-r--r--wasm2c/wasm-rt-impl.h8
-rw-r--r--wasm2c/wasm-rt.h54
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`.
*