summaryrefslogtreecommitdiff
path: root/wasm2c
diff options
context:
space:
mode:
Diffstat (limited to 'wasm2c')
-rw-r--r--wasm2c/examples/callback/main.c3
-rw-r--r--wasm2c/examples/fac/fac.c32
-rw-r--r--wasm2c/wasm-rt-impl.c2
-rw-r--r--wasm2c/wasm-rt.h15
4 files changed, 45 insertions, 7 deletions
diff --git a/wasm2c/examples/callback/main.c b/wasm2c/examples/callback/main.c
index 8c6f9db0..8d9ab59e 100644
--- a/wasm2c/examples/callback/main.c
+++ b/wasm2c/examples/callback/main.c
@@ -26,7 +26,8 @@ int main(int argc, char** argv) {
*/
wasm_rt_func_type_t fn_type =
wasm2c_callback_get_func_type(1, 0, WASM_RT_I32);
- wasm_rt_funcref_t fn_ref = {fn_type, (wasm_rt_function_ptr_t)print, &inst};
+ wasm_rt_funcref_t fn_ref = {
+ fn_type, (wasm_rt_function_ptr_t)print, {NULL}, &inst};
w2c_callback_set_print_function(&inst, fn_ref);
/* "say_hello" uses the previously installed callback. */
diff --git a/wasm2c/examples/fac/fac.c b/wasm2c/examples/fac/fac.c
index f6d6d0de..33151cdd 100644
--- a/wasm2c/examples/fac/fac.c
+++ b/wasm2c/examples/fac/fac.c
@@ -39,11 +39,16 @@ static inline bool func_types_eq(const wasm_rt_func_type_t a,
return (a == b) || LIKELY(a && b && !memcmp(a, b, 32));
}
-#define CALL_INDIRECT(table, t, ft, x, ...) \
+#define CHECK_CALL_INDIRECT(table, ft, x) \
(LIKELY((x) < table.size && table.data[x].func && \
func_types_eq(ft, table.data[x].func_type)) || \
- TRAP(CALL_INDIRECT), \
- ((t)table.data[x].func)(__VA_ARGS__))
+ TRAP(CALL_INDIRECT))
+
+#define DO_CALL_INDIRECT(table, t, x, ...) ((t)table.data[x].func)(__VA_ARGS__)
+
+#define CALL_INDIRECT(table, t, ft, x, ...) \
+ (CHECK_CALL_INDIRECT(table, ft, x), \
+ DO_CALL_INDIRECT(table, t, x, __VA_ARGS__))
#ifdef SUPPORT_MEMORY64
#define RANGE_CHECK(mem, offset, len) \
@@ -522,6 +527,7 @@ typedef struct {
enum { RefFunc, RefNull, GlobalGet } expr_type;
wasm_rt_func_type_t type;
wasm_rt_function_ptr_t func;
+ wasm_rt_tailcallee_t func_tailcallee;
size_t module_offset;
} wasm_elem_segment_expr_t;
@@ -542,7 +548,7 @@ static inline void funcref_table_init(wasm_rt_funcref_table_t* dest,
switch (src_expr->expr_type) {
case RefFunc:
*dest_val = (wasm_rt_funcref_t){
- src_expr->type, src_expr->func,
+ src_expr->type, src_expr->func, src_expr->func_tailcallee,
(char*)module_instance + src_expr->module_offset};
break;
case RefNull:
@@ -633,6 +639,24 @@ DEFINE_TABLE_FILL(externref)
#define FUNC_TYPE_T(x) static const char x[]
#endif
+#if (__STDC_VERSION__ < 201112L) && !defined(static_assert)
+#define static_assert(X) \
+ extern int(*assertion(void))[!!sizeof(struct { int x : (X) ? 2 : -1; })];
+#endif
+
+#ifdef _MSC_VER
+#define WEAK_FUNC_DECL(func, fallback) \
+ __pragma(comment(linker, "/alternatename:" #func "=" #fallback)) \
+ \
+ void \
+ fallback(void** instance_ptr, void* tail_call_stack, \
+ wasm_rt_tailcallee_t* next)
+#else
+#define WEAK_FUNC_DECL(func, fallback) \
+ __attribute__((weak)) void func(void** instance_ptr, void* tail_call_stack, \
+ wasm_rt_tailcallee_t* next)
+#endif
+
static u32 w2c_fac_fac_0(w2c_fac*, u32);
FUNC_TYPE_T(w2c_fac_t0) = "\x07\x80\x96\x7a\x42\xf7\x3e\xe6\x70\x5c\x2f\xac\x83\xf5\x67\xd2\xa2\xa0\x69\x41\x5f\xf8\xe7\x96\x7f\x23\xab\x00\x03\x5f\x4a\x3c";
diff --git a/wasm2c/wasm-rt-impl.c b/wasm2c/wasm-rt-impl.c
index 54223087..99bae707 100644
--- a/wasm2c/wasm-rt-impl.c
+++ b/wasm2c/wasm-rt-impl.c
@@ -414,7 +414,7 @@ const char* wasm_rt_strerror(wasm_rt_trap_t trap) {
case WASM_RT_TRAP_UNREACHABLE:
return "Unreachable instruction executed";
case WASM_RT_TRAP_CALL_INDIRECT:
- return "Invalid call_indirect";
+ return "Invalid call_indirect or return_call_indirect";
case WASM_RT_TRAP_UNCAUGHT_EXCEPTION:
return "Uncaught exception";
case WASM_RT_TRAP_UNALIGNED:
diff --git a/wasm2c/wasm-rt.h b/wasm2c/wasm-rt.h
index bdeecd56..e6df7d09 100644
--- a/wasm2c/wasm-rt.h
+++ b/wasm2c/wasm-rt.h
@@ -246,6 +246,17 @@ typedef enum {
typedef void (*wasm_rt_function_ptr_t)(void);
/**
+ * A pointer to a "tail-callee" function, called by a tail-call
+ * trampoline or by another tail-callee function. (The definition uses a
+ * single-member struct to allow a recursive definition.)
+ */
+typedef struct wasm_rt_tailcallee_t {
+ void (*fn)(void** instance_ptr,
+ void* tail_call_stack,
+ struct wasm_rt_tailcallee_t* next);
+} wasm_rt_tailcallee_t;
+
+/**
* The type of a function (an arbitrary number of param and result types).
* This is represented as an opaque 256-bit ID.
*/
@@ -259,6 +270,8 @@ typedef struct {
/** The function. The embedder must know the actual C signature of the
* function and cast to it before calling. */
wasm_rt_function_ptr_t func;
+ /** An alternate version of the function to be used when tail-called. */
+ wasm_rt_tailcallee_t func_tailcallee;
/** A function instance is a closure of the function over an instance
* of the originating module. The module_instance element will be passed into
* the function at runtime. */
@@ -266,7 +279,7 @@ typedef struct {
} wasm_rt_funcref_t;
/** Default (null) value of a funcref */
-static const wasm_rt_funcref_t wasm_rt_funcref_null_value = {NULL, NULL, NULL};
+static const wasm_rt_funcref_t wasm_rt_funcref_null_value;
/** The type of an external reference (opaque to WebAssembly). */
typedef void* wasm_rt_externref_t;