Remove native C bindings. Validate args for Raw calls. Cleanup

extensions
Volodymyr Shymanskyy 5 years ago
parent 9eec29286c
commit 93c50b5882

@ -163,15 +163,11 @@ d_m3ErrorConst (trapIntegerConversion, "[trap] invalid conversion to in
d_m3ErrorConst (trapIndirectCallTypeMismatch, "[trap] indirect call type mismatch")
d_m3ErrorConst (trapTableIndexOutOfRange, "[trap] undefined element")
d_m3ErrorConst (trapExit, "[trap] program called exit")
d_m3ErrorConst (trapAbort, "[trap] program called abort")
d_m3ErrorConst (trapUnreachable, "[trap] unreachable executed")
d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow")
typedef void (* M3Free) (const void * i_data, void * i_ref);
typedef void (* M3Importer) (IM3ImportInfo io_import, IM3Module io_module, void * i_ref);
typedef int64_t (* M3Callback) (IM3Function i_currentFunction, void * i_ref);
//-------------------------------------------------------------------------------------------------------------------------------
// configuration (found in m3_core.h)
//-------------------------------------------------------------------------------------------------------------------------------
@ -200,18 +196,8 @@ typedef int64_t (* M3Callback) (IM3Function i_currentFunction, void * i_ref);
uint32_t i_stackSizeInBytes,
M3StackInfo * i_nativeStackInfo); // i_nativeStackInfo can be NULL
M3Result m3_RegisterFunction (IM3Runtime io_runtime,
const char * const i_functionName,
const char * const i_signature,
const void * const i_function /* , const void * const i_ref */);
void m3_FreeRuntime (IM3Runtime i_runtime);
// void m3_SetImporter (IM3Runtime i_runtime, M3Importer i_importHandler);
// void m3_SetTimeoutHandler (IM3Runtime i_runtime, float i_periodInSeconds, M3Callback i_callback);
//--------------------------------------------------------------------------------------------------------------------------------------------
// modules
//--------------------------------------------------------------------------------------------------------------------------------------------
@ -230,9 +216,6 @@ typedef int64_t (* M3Callback) (IM3Function i_currentFunction, void * i_ref);
void m3_FreeModule (IM3Module i_module);
// Only unloaded modules need to be freed.
// M3Result m3_EnableOptimizer (IM3Module io_module, bool i_enable);
M3Result m3_LoadModule (IM3Runtime io_runtime, IM3Module io_module);
// LoadModule transfers ownership of a module to the runtime. Do not free modules once successfully imported into the runtime.
@ -243,19 +226,8 @@ typedef int64_t (* M3Callback) (IM3Function i_currentFunction, void * i_ref);
M3Result m3_LinkRawFunction (IM3Module io_module,
const char * const i_moduleName,
const char * const i_functionName,
M3RawCall i_function); // void (u64 * _sp, u8 * _mem)
M3Result m3_LinkCFunction (IM3Module io_module,
const char * const i_moduleName,
const char * const i_functionName,
const char * const i_signature, // signature is null terminated
const void * const i_function /* , const void * const i_ref */);
// M3Result m3_SetGlobal
const char * const i_signature,
M3RawCall i_function);
//--------------------------------------------------------------------------------------------------------------------------------------------
// functions
@ -265,15 +237,10 @@ typedef int64_t (* M3Callback) (IM3Function i_currentFunction, void * i_ref);
IM3Runtime i_runtime,
const char * const i_functionName);
// M3Result m3_GetCFunction (void ** o_cFunction, IM3Runtime i_runtime,
// const char * const i_functionName, const char * const i_signature);
M3Result m3_Call (IM3Function i_function);
M3Result m3_CallWithArgs (IM3Function i_function, uint32_t i_argc, const char * const * i_argv);
// M3Result m3_CallMain (IM3Function i_function, uint32_t i_argc, const char * const * i_argv);
// void * /* return */ m3_Call (IM3Function i_function, M3Result * o_result);
// IM3Functions are valid during the lifetime of the originating runtime
M3ErrorInfo m3_GetErrorInfo (IM3Runtime i_runtime);

@ -10,12 +10,16 @@
#include "m3_core.h"
// TODO: perform bounds checks
#define m3ApiOffsetToPtr(offset) (void*)((u8*)_mem + (u32)(offset))
#define m3ApiPtrToOffset(ptr) (u32)((u8*)ptr - (u8*)_mem)
#define m3ApiReturnType(TYPE) TYPE* raw_return = ((TYPE*) (_sp));
#define m3ApiGetArg(TYPE, NAME) TYPE NAME = * ((TYPE *) (_sp++));
#define m3ApiGetArgMem(TYPE, NAME) TYPE NAME = (TYPE)(void*)((u8*)_mem + * (u32 *) _sp++);
#define m3ApiGetArgMem(TYPE, NAME) TYPE NAME = (TYPE)m3ApiOffsetToPtr(* ((u32 *) (_sp++)));
#define m3ApiRawFunction(NAME) const void * NAME (IM3Runtime runtime, uint64_t * _sp, void * _mem)
#define m3ApiReturn(VALUE) { *raw_return = (VALUE); return NULL; }
#define m3ApiReturn(VALUE) { *raw_return = (VALUE); return c_m3Err_none; }
#define m3ApiTrap(VALUE) { return VALUE; }
#endif /* m3_api_defs_h */

@ -19,58 +19,50 @@
#include <stdio.h>
#if defined(WIN32)
#include <Windows.h>
int clock_gettime(int clk_id, struct timespec *spec)
m3ApiRawFunction(m3_libc_abort)
{
__int64 wintime;
GetSystemTimeAsFileTime((FILETIME*)&wintime);
wintime -=116444736000000000i64; //1jan1601 to 1jan1970
spec->tv_sec =wintime / 10000000i64; //seconds
spec->tv_nsec =wintime % 10000000i64 *100; //nano-seconds
return 0;
m3ApiTrap(c_m3Err_trapAbort);
}
#endif
// TODO: return trap
void m3_libc_abort()
m3ApiRawFunction(m3_libc_exit)
{
abort ();
m3ApiGetArg (int32_t, code)
m3ApiTrap(c_m3Err_trapExit);
}
m3ret_t m3_libc_exit (i32 i_code)
m3ApiRawFunction(m3_libc_memset)
{
printf ("exit (%d)\n", i_code);
m3ApiReturnType (int32_t)
return c_m3Err_trapExit;
}
m3ApiGetArgMem (void*, i_ptr)
m3ApiGetArg (int32_t, i_value)
m3ApiGetArg (int32_t, i_size)
void* m3_libc_memset(void * i_ptr, i32 i_value, i32 i_size)
{
memset (i_ptr, i_value, i_size);
return i_ptr;
u32 result = m3ApiPtrToOffset(memset (i_ptr, i_value, i_size));
m3ApiReturn(result);
}
void* m3_libc_memcpy(void * o_dst, void * i_src, i32 i_size)
m3ApiRawFunction(m3_libc_memmove)
{
return memcpy (o_dst, i_src, i_size);
}
m3ApiReturnType (int32_t)
uint32_t m3_libc_clock()
{
return clock();
m3ApiGetArgMem (void*, o_dst)
m3ApiGetArgMem (void*, i_src)
m3ApiGetArg (int32_t, i_size)
u32 result = m3ApiPtrToOffset(memmove (o_dst, i_src, i_size));
m3ApiReturn(result);
}
uint32_t m3_libc_clock_gettime(uint32_t clk_id, struct timespec* tp)
m3ApiRawFunction(m3_libc_clock)
{
return clock_gettime(clk_id, tp);
}
m3ApiReturnType (uint32_t)
m3ApiReturn(clock());
}
static
M3Result SuppressLookupFailure (M3Result i_result)
@ -99,10 +91,12 @@ m3ApiRawFunction(m3_wasm3_raw_sum)
return c_m3Err_none;
}
/* TODO: implement direct native function calls (using libffi?)
i64 m3_wasm3_native_sum(i32 val1, i32 val2, i32 val3, i32 val4)
{
return val1 + val2 + val3 + val4;
}
*/
M3Result m3_LinkSpecTest (IM3Module module)
@ -110,19 +104,19 @@ M3Result m3_LinkSpecTest (IM3Module module)
M3Result result = c_m3Err_none;
const char* spectest = "spectest";
const char* wasm3 = "wasm3";
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_i32", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_i64", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_f32", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_f64", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_i32_f32", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_i64_f64", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print", "v()", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_i32", "v(i)", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_i64", "v(I)", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_f32", "v(f)", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_f64", "v(F)", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_i32_f32", "v(if)", &m3_spectest_dummy)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, spectest, "print_i64_f64", "v(IF)", &m3_spectest_dummy)));
const char* wasm3 = "wasm3";
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasm3, "raw_sum", &m3_wasm3_raw_sum)));
_ (SuppressLookupFailure (m3_LinkCFunction (module, wasm3, "native_sum", "I(iiii)", &m3_wasm3_native_sum)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasm3, "raw_sum", "I(iiii)", &m3_wasm3_raw_sum)));
//_ (SuppressLookupFailure (m3_LinkCFunction (module, wasm3, "native_sum", "I(iiii)", &m3_wasm3_native_sum)));
_catch:
return result;
@ -133,19 +127,14 @@ M3Result m3_LinkLibC (IM3Module module)
{
M3Result result = c_m3Err_none;
const char* namespace = "env";
//_ (SuppressLookupFailure (m3_LinkFunction (module, "_printf", "v(**)", &m3_libc_printf)));
//_ (SuppressLookupFailure (m3_LinkFunction (module, "g$_stderr", "i(M)", &m3_libc_get_stderr)));
_ (SuppressLookupFailure (m3_LinkCFunction (module, namespace, "_memset", "*(*ii)", &m3_libc_memset)));
_ (SuppressLookupFailure (m3_LinkCFunction (module, namespace, "_memcpy", "*(**i)", &m3_libc_memcpy)));
_ (SuppressLookupFailure (m3_LinkCFunction (module, namespace, "_exit", "Tv(i)", &m3_libc_exit)));
_ (SuppressLookupFailure (m3_LinkCFunction (module, namespace, "_perror", "v(*)", &perror)));
_ (SuppressLookupFailure (m3_LinkCFunction (module, namespace, "_clock", "i()", &m3_libc_clock)));
_ (SuppressLookupFailure (m3_LinkCFunction (module, namespace, "_clock_gettime", "i(i*)", &m3_libc_clock_gettime)));
const char* env = "env";
_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "_memset", "*(*ii)", &m3_libc_memset)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "_memmove", "*(**i)", &m3_libc_memmove)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "_memcpy", "*(**i)", &m3_libc_memmove))); // just alias of memmove
_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "_abort", "v()", &m3_libc_abort)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "_exit", "v(i)", &m3_libc_exit)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "_clock", "i()", &m3_libc_clock)));
_catch:
return result;

@ -627,7 +627,7 @@ M3Result m3_LinkWASI (IM3Module module)
{
M3Result result = c_m3Err_none;
const char* namespace = "wasi_unstable";
const char* wasi = "wasi_unstable";
#ifdef _WIN32
setmode(fileno(stdin), O_BINARY);
@ -640,31 +640,31 @@ M3Result m3_LinkWASI (IM3Module module)
preopen[i].fd = open(preopen[i].path, O_RDONLY);
}
#endif
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "args_sizes_get", &m3_wasi_unstable_args_sizes_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "environ_sizes_get", &m3_wasi_unstable_environ_sizes_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "args_get", &m3_wasi_unstable_args_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "environ_get", &m3_wasi_unstable_environ_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_unstable_args_sizes_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_unstable_environ_sizes_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_get", "i(**)", &m3_wasi_unstable_args_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_unstable_environ_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "fd_prestat_dir_name", &m3_wasi_unstable_fd_prestat_dir_name)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "fd_prestat_get", &m3_wasi_unstable_fd_prestat_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_unstable_fd_prestat_dir_name)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_unstable_fd_prestat_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "path_open", &m3_wasi_unstable_path_open)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiiii*)", &m3_wasi_unstable_path_open)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "fd_fdstat_get", &m3_wasi_unstable_fd_fdstat_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "fd_write", &m3_wasi_unstable_fd_write)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "fd_read", &m3_wasi_unstable_fd_read)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "fd_seek", &m3_wasi_unstable_fd_seek)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "fd_datasync", &m3_wasi_unstable_fd_datasync)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "fd_close", &m3_wasi_unstable_fd_close)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_unstable_fd_fdstat_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(iii*)", &m3_wasi_unstable_fd_write)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(iii*)", &m3_wasi_unstable_fd_read)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_seek", "i(iii*)", &m3_wasi_unstable_fd_seek)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_unstable_fd_datasync)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_unstable_fd_close)));
//_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "sock_send", &...)));
//_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "sock_recv", &...)));
//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i()", &...)));
//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i()", &...)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "random_get", &m3_wasi_unstable_random_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_unstable_random_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "clock_res_get", &m3_wasi_unstable_clock_res_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "clock_time_get", &m3_wasi_unstable_clock_time_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "proc_exit", &m3_wasi_unstable_proc_exit)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_unstable_clock_res_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(ii*)", &m3_wasi_unstable_clock_time_get)));
_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_exit", "i(i)", &m3_wasi_unstable_proc_exit)));
_catch:
return result;

@ -10,191 +10,30 @@
#include "m3_env.h"
#include "m3_exception.h"
typedef struct M3State
{
pc_t pc;
m3stack_t sp;
u8 * mem;
}
M3State;
// TODO: This binding code only work'n for System V AMD64 ABI calling convention (macOS & Linux)
// Needs work for MS cdecl
#define d_m3BindingArgList i64 _i0, i64 _i1, i64 _i2, i64 _i3, i64 _i4, i64 _i5, \
f64 _f0, f64 _f1, f64 _f2, f64 _f3, f64 _f4
#define d_m3BindingArgs _i0, _i1, _i2, _i3, _i4, _i5, \
_f0, _f1, _f2, _f3, _f4
#define d_m3BindingDefaultArgs 0,0,0,0,0,0, \
0.,0.,0.,0.,0.
typedef m3ret_t (* M3ArgPusher) (d_m3BindingArgList, M3State * i_state);
typedef f64 (* M3ArgPusherFpReturn) (d_m3BindingArgList, M3State * i_state);
m3ret_t PushArg_runtime (d_m3BindingArgList, M3State * _state)
{
M3MemoryHeader * info = (M3MemoryHeader *) _state->mem - 1;
_i0 = (i64) info->runtime;
M3ArgPusher pusher = (M3ArgPusher)(* _state->pc++);
return pusher (d_m3BindingArgs, _state);
}
#define d_argPusherPointer(INDEX) \
m3ret_t PushArg_p##INDEX (d_m3BindingArgList, M3State * _state) \
{ \
i32 offset = (u32) * (_state->sp++); \
_i##INDEX = (i64) (_state->mem + offset); \
M3ArgPusher pusher = (M3ArgPusher)(* _state->pc++); \
return pusher (d_m3BindingArgs, _state); \
}
//printf ("push ptr: r%d off: %d\n", INDEX, offset);
//printf ("push [%d]: %" PRId64 "\n", INDEX, _i##INDEX);
#define d_argPusherInt(INDEX) \
m3ret_t PushArg_i##INDEX (d_m3BindingArgList, M3State * _state) \
{ \
_i##INDEX = * (_state->sp++); \
M3ArgPusher pusher = (M3ArgPusher)(* _state->pc++); \
return pusher (d_m3BindingArgs, _state); \
}
//printf ("push [%d]: %lf\n", INDEX, * (TYPE *) (_state->sp));
#define d_argPusherFloat(INDEX,TYPE) \
m3ret_t PushArg_##TYPE##_##INDEX (d_m3BindingArgList, M3State * _state) \
{ \
_f##INDEX = * (TYPE *) (_state->sp++); \
M3ArgPusher pusher = (M3ArgPusher)(* _state->pc++); \
return pusher (d_m3BindingArgs, _state); \
}
d_argPusherPointer (0) d_argPusherPointer (1) d_argPusherPointer (2) d_argPusherPointer (3)
d_argPusherInt (0) d_argPusherInt (1) d_argPusherInt (2) d_argPusherInt (3)
d_argPusherFloat (0, f32) d_argPusherFloat (1, f32) d_argPusherFloat (2, f32) d_argPusherFloat (3, f32)
d_argPusherFloat (0, f64) d_argPusherFloat (1, f64) d_argPusherFloat (2, f64) d_argPusherFloat (3, f64)
d_argPusherPointer (4) d_argPusherPointer (5)
d_argPusherInt (4) d_argPusherInt (5)
d_argPusherFloat (4, f32)
d_argPusherFloat (4, f64)
M3ArgPusher c_m3PointerPushers [] = { PushArg_p0, PushArg_p1, PushArg_p2, PushArg_p3, PushArg_p4, PushArg_p5, NULL }; // one dummy is required
M3ArgPusher c_m3IntPushers [] = { PushArg_i0, PushArg_i1, PushArg_i2, PushArg_i3, PushArg_i4, PushArg_i5, NULL };
M3ArgPusher c_m3Float32Pushers [] = { PushArg_f32_0, PushArg_f32_1, PushArg_f32_2, PushArg_f32_3, PushArg_f32_4, NULL };
M3ArgPusher c_m3Float64Pushers [] = { PushArg_f64_0, PushArg_f64_1, PushArg_f64_2, PushArg_f64_3, PushArg_f64_4, NULL };
d_m3RetSig CallTrappingCFunction_void (d_m3OpSig)
{
M3ArgPusher pusher = (M3ArgPusher) (* _pc++);
M3State state = { _pc, _sp, m3MemData(_mem) };
m3ret_t r = (m3ret_t) pusher (d_m3BindingDefaultArgs, & state);
return r;
}
d_m3RetSig CallCFunction_i64 (d_m3OpSig)
{
M3ArgPusher pusher = (M3ArgPusher) (* _pc++);
M3State state = { _pc, _sp, m3MemData(_mem) };
i64 r = (i64) pusher (d_m3BindingDefaultArgs, & state);
* _sp = r;
return 0;
}
d_m3RetSig CallCFunction_f64 (d_m3OpSig)
{
M3ArgPusherFpReturn pusher = (M3ArgPusherFpReturn) (* _pc++);
M3State state = { _pc, _sp, m3MemData(_mem) };
f64 r = (f64) pusher (d_m3BindingDefaultArgs, & state);
* (f64 *) (_sp) = r;
return 0;
}
d_m3RetSig CallCFunction_f32 (d_m3OpSig)
{
M3ArgPusherFpReturn pusher = (M3ArgPusherFpReturn) (* _pc++);
M3State state = { _pc, _sp, m3MemData(_mem) };
f32 r = (f32) pusher (d_m3BindingDefaultArgs, & state);
* (f32 *) (_sp) = r;
return 0;
}
d_m3RetSig CallCFunction_ptr (d_m3OpSig)
{
M3ArgPusher pusher = (M3ArgPusher) (* _pc++);
M3State state = { _pc, _sp, m3MemData(_mem) };
const u8 * r = (const u8*) pusher (d_m3BindingDefaultArgs, & state);
size_t offset = r - m3MemData(_mem);
* (i32 *) (_sp) = (i32) offset;
return 0;
}
static
u8 ConvertTypeCharToTypeId (char i_code)
{
u8 type = 0;
// if (i_code > c_m3Type_ptr)
{
if (i_code == 'v') type = c_m3Type_void;
else if (i_code == '*') type = c_m3Type_ptr;
else if (i_code == 'T') type = c_m3Type_trap;
else if (i_code == '8') type = c_m3Type_i32;
else if (i_code == 'f') type = c_m3Type_f32;
else if (i_code == 'F') type = c_m3Type_f64;
else if (i_code == 'i') type = c_m3Type_i32;
else if (i_code == 'I') type = c_m3Type_i64;
else if (i_code == 'R') type = c_m3Type_runtime;
switch (i_code) {
case 'v': return c_m3Type_void;
case 'i': return c_m3Type_i32;
case 'I': return c_m3Type_i64;
case 'f': return c_m3Type_f32;
case 'F': return c_m3Type_f64;
case '*': return c_m3Type_ptr;
}
return type;
return c_m3Type_none;
}
M3Result ValidateSignature (IM3Function i_function, bool * o_traps, u8 * o_normalizedSignature, ccstr_t i_linkingSignature)
static
M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature)
{
M3Result result = c_m3Err_none;
* o_traps = false;
cstr_t sig = i_linkingSignature;
bool hasReturn = false;
u32 numArgs = 0;
// check for trap flag
u8 type = ConvertTypeCharToTypeId (* sig);
if (type == c_m3Type_trap)
{
* o_traps = true;
++sig;
}
bool parsingArgs = false;
while (* sig)
{
@ -216,15 +55,10 @@ M3Result ValidateSignature (IM3Function i_function, bool * o_traps, u8 * o_nor
else if (typeChar == ')')
break;
type = ConvertTypeCharToTypeId (typeChar);
u8 type = ConvertTypeCharToTypeId (typeChar);
if (type)
{
* o_normalizedSignature++ = type;
if (type == c_m3Type_trap)
_throw ("malformed function signature");
if (not parsingArgs)
{
if (hasReturn)
@ -247,118 +81,8 @@ M3Result ValidateSignature (IM3Function i_function, bool * o_traps, u8 * o_nor
_catch: return result;
}
M3Result m3_RegisterFunction (IM3Runtime io_runtime, const char * const i_functionName, const char * const i_signature, const void * const i_function /* , const void * const i_ref */)
{
M3Result result = c_m3Err_none;
return result;
}
typedef M3Result (* M3Linker) (IM3Module io_module, IM3Function io_function, const char * const i_signature, const void * i_function);
M3Result LinkCFunction (IM3Module io_module, IM3Function io_function, const char * const i_signature, const void * i_function)
{
M3Result result = c_m3Err_none;
M3ArgPusher pushers [c_m3MaxNumFunctionArgs + 1];
u8 signature [1 /* return */ + c_m3MaxNumFunctionArgs + 2];
M3_INIT(pushers);
M3_INIT(signature);
bool trappingFunction = false;
result = ValidateSignature (io_function, & trappingFunction, signature, i_signature);
if (not result)
{
u8 returnType = signature [0];
u8 * sig = & signature [1];
u32 intIndex = 0;
u32 floatIndex = 0;
u32 i = 0;
while (* sig)
{
M3ArgPusher * pusher = & pushers [i];
u8 type = * sig;
if (type == c_m3Type_ptr) * pusher = c_m3PointerPushers [intIndex++];
else if (IsIntType (type)) * pusher = c_m3IntPushers [intIndex++];
else if (type == c_m3Type_f32) * pusher = c_m3Float32Pushers [floatIndex++];
else if (type == c_m3Type_f64) * pusher = c_m3Float64Pushers [floatIndex++];
else if (type == c_m3Type_runtime)
{
* pusher = PushArg_runtime;
d_m3Assert (i == 0); // can only push to arg0
++intIndex;
}
else
{
result = "FIX";
m3NotImplemented();
}
if (* pusher == NULL)
_throw ("too many arguments in C binding");
++i; ++sig;
}
if (not result)
{
IM3CodePage page = AcquireCodePageWithCapacity (io_module->runtime, /*setup-func:*/ 1 + /*arg pushers:*/ i + /*target c-function:*/ 1);
if (page)
{
io_function->compiled = GetPagePC (page);
io_function->module = io_module;
IM3Operation callerOp;
if (trappingFunction)
{
// TODO: returned types not implemented!
d_m3Assert (returnType == c_m3Type_void);
callerOp = CallTrappingCFunction_void;
}
else
{
callerOp = CallCFunction_i64;
if (returnType == c_m3Type_f64)
callerOp = CallCFunction_f64;
else if (returnType == c_m3Type_f32)
callerOp = CallCFunction_f32;
else if (returnType == c_m3Type_ptr)
callerOp = CallCFunction_ptr;
}
EmitWord (page, callerOp);
for (u32 j = 0; j < i; ++j)
EmitWord (page, pushers [j]);
EmitWord (page, i_function);
ReleaseCodePage (io_module->runtime, page);
}
else result = c_m3Err_mallocFailedCodePage;
}
}
_catch:
return result;
}
M3Result FindAndLinkFunction (IM3Module io_module,
ccstr_t i_moduleName,
ccstr_t i_functionName,
@ -386,25 +110,15 @@ M3Result FindAndLinkFunction (IM3Module io_module,
return result;
}
M3Result m3_LinkCFunction (IM3Module io_module,
const char * const i_moduleName,
const char * const i_functionName,
const char * const i_signature,
const void * i_function)
{
return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, i_function, LinkCFunction);
}
// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// TODO: validate signature as well?
M3Result LinkRawFunction (IM3Module io_module, IM3Function io_function, ccstr_t signature, const void * i_function)
{
M3Result result = c_m3Err_none; d_m3Assert (io_module->runtime);
_try {
_ (ValidateSignature (io_function, signature));
IM3CodePage page = AcquireCodePageWithCapacity (io_module->runtime, 2);
if (page)
@ -417,8 +131,9 @@ M3Result LinkRawFunction (IM3Module io_module, IM3Function io_function, ccstr
ReleaseCodePage (io_module->runtime, page);
}
else result = c_m3Err_mallocFailedCodePage;
else _throw(c_m3Err_mallocFailedCodePage);
} _catch:
return result;
}
@ -426,9 +141,10 @@ M3Result LinkRawFunction (IM3Module io_module, IM3Function io_function, ccstr
M3Result m3_LinkRawFunction (IM3Module io_module,
const char * const i_moduleName,
const char * const i_functionName,
const char * const i_signature,
M3RawCall i_function)
{
return FindAndLinkFunction (io_module, i_moduleName, i_functionName, NULL, i_function, LinkRawFunction);
return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, i_function, LinkRawFunction);
}

@ -42,7 +42,7 @@ commands = [
"args": ["cat", "./wasi/0.txt"],
"expect_pattern": "Hello world*Constructor OK*Args: *; cat; ./wasi/0.txt;*fib(20) = 6765*[* ms]*48 65 6c 6c 6f 20 77 6f 72 6c 64*=== done ===*"
}, {
"skip": True, # TODO: Native calls fail on all 32-bit targets
"skip": True, # Direct native calls were removed from wasm3
"name": "Raw/Native funcs benchmark",
"wasm": "./wasi/test_native_vs_raw.wasm",
"expect_pattern": "Validation...*Native/Raw: *"

@ -4,6 +4,14 @@
#include "wasm_api.h"
/*
* Result: "Raw" calls are ~2x faster than native arg "pushers".
*
* WARNING: this benchmark no longer works.
* Native calls were removed along with wasm3_native_sum.
* It may be useful in future when we implement libffi calls, etc.
*/
static inline
double get_time() {
struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts);

@ -12,7 +12,4 @@
WASM_IMPORT("wasm3", "raw_sum")
int64_t wasm3_raw_sum (int32_t val1, int32_t val2, int32_t val3, int32_t val4);
WASM_IMPORT("wasm3", "native_sum")
int64_t wasm3_native_sum (int32_t val1, int32_t val2, int32_t val3, int32_t val4);
#endif

@ -1,2 +1 @@
wasm3_raw_sum
wasm3_native_sum

Loading…
Cancel
Save