diff options
Diffstat (limited to 'wasm2c')
-rw-r--r-- | wasm2c/examples/callback/main.c | 3 | ||||
-rw-r--r-- | wasm2c/examples/fac/fac.c | 32 | ||||
-rw-r--r-- | wasm2c/wasm-rt-impl.c | 2 | ||||
-rw-r--r-- | wasm2c/wasm-rt.h | 15 |
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; |