diff --git a/platforms/android/app/src/main/cpp/main.c b/platforms/android/app/src/main/cpp/main.c index 290d0ec..81a46f6 100644 --- a/platforms/android/app/src/main/cpp/main.c +++ b/platforms/android/app/src/main/cpp/main.c @@ -10,7 +10,6 @@ #include #include "m3/wasm3.h" -#include "m3/m3_env.h" #include "m3/m3_config.h" #include "m3/extra/fib32.wasm.h" @@ -45,10 +44,9 @@ void run_wasm() printf("Running...\n"); - const char* i_argv[2] = { "40", NULL }; - result = m3_CallWithArgs (f, 1, i_argv); + result = m3_CallV (f, 40); - if (result) FATAL("m3_CallWithArgs: %s", result); + if (result) FATAL("m3_Call: %s", result); long value = *(uint64_t*)(runtime->stack); printf("Result: %ld\n", value); diff --git a/platforms/app/main.c b/platforms/app/main.c index 59193ea..065fbf9 100644 --- a/platforms/app/main.c +++ b/platforms/app/main.c @@ -14,7 +14,6 @@ #include "m3_api_wasi.h" #include "m3_api_libc.h" #include "m3_api_tracer.h" -#include "m3_env.h" #define FATAL(msg, ...) { printf("Error: [Fatal] " msg "\n", ##__VA_ARGS__); goto _onfatal; } @@ -157,7 +156,7 @@ M3Result repl_call (const char* name, int argc, const char* argv[]) M3Result result = m3_FindFunction (&func, runtime, "_start"); if (result) return result; - result = m3_CallWithArgs(func, 0, NULL); + result = m3_CallArgV(func, 0, NULL); if (result == m3Err_trapExit) { exit(wasi_ctx->exit_code); @@ -170,31 +169,36 @@ M3Result repl_call (const char* name, int argc, const char* argv[]) } int arg_count = m3_GetArgCount(func); + int ret_count = m3_GetRetCount(func); if (argc < arg_count) { return "not enough arguments"; } else if (argc > arg_count) { return "too many arguments"; } - result = m3_CallWithArgs (func, argc, argv); + result = m3_CallArgV (func, argc, argv); if (result) return result; - // TODO: Stack access API - uint64_t* stack = (uint64_t*)runtime->stack; + static uint64_t valbuff[128]; + static const void* valptrs[128]; + memset(valbuff, 0, sizeof(valbuff)); + for (int i = 0; i < ret_count; i++) { + valptrs[i] = &valbuff[i]; + } + result = m3_GetResults (func, ret_count, valptrs); + if (result) return result; - int ret_count = m3_GetRetCount(func); if (ret_count <= 0) { fprintf (stderr, "Result: \n"); } for (int i = 0; i < ret_count; i++) { switch (m3_GetRetType(func, i)) { - case c_m3Type_i32: fprintf (stderr, "Result: %" PRIi32 "\n", *(i32*)(stack)); break; - case c_m3Type_i64: fprintf (stderr, "Result: %" PRIi64 "\n", *(i64*)(stack)); break; - case c_m3Type_f32: fprintf (stderr, "Result: %f\n", *(f32*)(stack)); break; - case c_m3Type_f64: fprintf (stderr, "Result: %lf\n", *(f64*)(stack)); break; + case c_m3Type_i32: fprintf (stderr, "Result: %" PRIi32 "\n", *(i32*)valptrs[i]); break; + case c_m3Type_i64: fprintf (stderr, "Result: %" PRIi64 "\n", *(i64*)valptrs[i]); break; + case c_m3Type_f32: fprintf (stderr, "Result: %" PRIf32 "\n", *(f32*)valptrs[i]); break; + case c_m3Type_f64: fprintf (stderr, "Result: %" PRIf64 "\n", *(f64*)valptrs[i]); break; default: return "unknown return type"; } - stack++; } return result; @@ -208,6 +212,8 @@ M3Result repl_invoke (const char* name, int argc, const char* argv[]) if (result) return result; int arg_count = m3_GetArgCount(func); + int ret_count = m3_GetRetCount(func); + if (argc > 128) { return "arguments limit reached"; } else if (argc < arg_count) { @@ -216,14 +222,14 @@ M3Result repl_invoke (const char* name, int argc, const char* argv[]) return "too many arguments"; } - static uint64_t argbuff[128]; - static const void* argptrs[128]; - memset(argbuff, 0, sizeof(argbuff)); - memset(argptrs, 0, sizeof(argptrs)); + static uint64_t valbuff[128]; + static const void* valptrs[128]; + memset(valbuff, 0, sizeof(valbuff)); + memset(valptrs, 0, sizeof(valptrs)); for (int i = 0; i < argc; i++) { - u64* s = &argbuff[i]; - argptrs[i] = s; + u64* s = &valbuff[i]; + valptrs[i] = s; switch (m3_GetArgType(func, i)) { case c_m3Type_i32: case c_m3Type_f32: *(u32*)(s) = strtoul(argv[i], NULL, 10); break; @@ -233,27 +239,30 @@ M3Result repl_invoke (const char* name, int argc, const char* argv[]) } } - result = m3_Call (func, argc, argptrs); + result = m3_Call (func, argc, valptrs); if (result) return result; - // TODO: Stack access API - uint64_t* stack = (uint64_t*)runtime->stack; + // reuse valbuff for return values + memset(valbuff, 0, sizeof(valbuff)); + for (int i = 0; i < ret_count; i++) { + valptrs[i] = &valbuff[i]; + } + result = m3_GetResults (func, ret_count, valptrs); + if (result) return result; - unsigned ret_count = m3_GetRetCount(func); if (ret_count <= 0) { fprintf (stderr, "Result: \n"); } - for (unsigned i = 0; i < ret_count; i++) { + for (int i = 0; i < ret_count; i++) { switch (m3_GetRetType(func, i)) { case c_m3Type_i32: case c_m3Type_f32: - fprintf (stderr, "Result: %" PRIu32 "\n", *(u32*)(stack)); break; + fprintf (stderr, "Result: %" PRIu32 "\n", *(u32*)valptrs[i]); break; case c_m3Type_i64: case c_m3Type_f64: - fprintf (stderr, "Result: %" PRIu64 "\n", *(u64*)(stack)); break; + fprintf (stderr, "Result: %" PRIu64 "\n", *(u64*)valptrs[i]); break; default: return "unknown return type"; } - stack++; } return result; diff --git a/platforms/app_fuzz/fuzzer.c b/platforms/app_fuzz/fuzzer.c index 965a0a9..86a1ee6 100644 --- a/platforms/app_fuzz/fuzzer.c +++ b/platforms/app_fuzz/fuzzer.c @@ -41,8 +41,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) IM3Function f = NULL; result = m3_FindFunction (&f, runtime, "fib"); if (f) { - const char* i_argv[1] = { "10", NULL }; - m3_CallWithArgs (f, 1, i_argv); + m3_CallV (f, 10); } } diff --git a/platforms/arduino/src/main.cpp b/platforms/arduino/src/main.cpp index d473b6d..fec0663 100644 --- a/platforms/arduino/src/main.cpp +++ b/platforms/arduino/src/main.cpp @@ -44,7 +44,7 @@ void run_wasm() Serial.println("Running..."); - result = m3_CallVariadic(f, 1, 24); + result = m3_CallV(f, 24); if (result) FATAL("m3_Call", result); long value = *(uint64_t*)(runtime->stack); diff --git a/platforms/bluepill/src/main.cpp b/platforms/bluepill/src/main.cpp index 6b2f3b4..6da3a47 100644 --- a/platforms/bluepill/src/main.cpp +++ b/platforms/bluepill/src/main.cpp @@ -44,7 +44,7 @@ void run_wasm() puts("Running..."); - result = m3_CallVariadic(f, 1, 24); + result = m3_CallV (f, 24); if (result) FATAL("m3_Call", result); long value = *(uint64_t*)(runtime->stack); diff --git a/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h b/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h index 4bf91ef..a3ad15a 100644 --- a/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h +++ b/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h @@ -309,7 +309,7 @@ namespace wasm3 { call_argv(Args... args) { /* std::enable_if above checks that all argument types are convertible const char* */ const char* argv[] = {args...}; - M3Result res = m3_CallWithArgs(m_func, sizeof...(args), argv); + M3Result res = m3_CallArgV(m_func, sizeof...(args), argv); detail::check_error(res); Ret ret; /* FIXME: there should be a public API to get the return value */ diff --git a/platforms/emscripten/main.c b/platforms/emscripten/main.c index fff595e..9b82a65 100644 --- a/platforms/emscripten/main.c +++ b/platforms/emscripten/main.c @@ -50,8 +50,7 @@ void run_wasm() result = m3_FindFunction (&f, runtime, "fib"); if (result) FATAL("m3_FindFunction: %s", result); - const char* i_argv[2] = { "40", NULL }; - result = m3_CallWithArgs (f, 1, i_argv); + result = m3_CallV (f, 40); if (result) FATAL("Call: %s", result); diff --git a/platforms/emscripten_lib/main.c b/platforms/emscripten_lib/main.c index cfb828d..8e80aa7 100644 --- a/platforms/emscripten_lib/main.c +++ b/platforms/emscripten_lib/main.c @@ -50,7 +50,7 @@ uint32_t call(IM3Runtime runtime, int argc, const char* argv[]) { result = m3_FindFunction (&f, runtime, argv[0]); if (result) return -1; - result = m3_CallWithArgs (f, argc-1, argv+1); + result = m3_CallArgV (f, argc-1, argv+1); if (result) return -2; return *(uint64_t*)(runtime->stack); diff --git a/platforms/esp32-idf-wasi/main/main.cpp b/platforms/esp32-idf-wasi/main/main.cpp index 3b623ba..61f35cf 100644 --- a/platforms/esp32-idf-wasi/main/main.cpp +++ b/platforms/esp32-idf-wasi/main/main.cpp @@ -50,7 +50,7 @@ static void run_wasm(void) printf("Running...\n"); const char* i_argv[2] = { "test.wasm", NULL }; - result = m3_CallWithArgs (f, 1, i_argv); + result = m3_CallArgV (f, 1, i_argv); if (result) FATAL("m3_CallWithArgs: %s", result); diff --git a/platforms/esp32-idf/main/main.cpp b/platforms/esp32-idf/main/main.cpp index 868a748..cecc187 100644 --- a/platforms/esp32-idf/main/main.cpp +++ b/platforms/esp32-idf/main/main.cpp @@ -45,7 +45,7 @@ static void run_wasm(void) printf("Running...\n"); - result = m3_CallVariadic(f, 1, 24); + result = m3_CallV(f, 24); if (result) FATAL("m3_Call: %s", result); long value = *(uint64_t*)(runtime->stack); diff --git a/platforms/esp32-pio/src/main.cpp b/platforms/esp32-pio/src/main.cpp index 868a748..cecc187 100644 --- a/platforms/esp32-pio/src/main.cpp +++ b/platforms/esp32-pio/src/main.cpp @@ -45,7 +45,7 @@ static void run_wasm(void) printf("Running...\n"); - result = m3_CallVariadic(f, 1, 24); + result = m3_CallV(f, 24); if (result) FATAL("m3_Call: %s", result); long value = *(uint64_t*)(runtime->stack); diff --git a/platforms/esp8266/src/main.cpp b/platforms/esp8266/src/main.cpp index f75fd6f..136b0cd 100644 --- a/platforms/esp8266/src/main.cpp +++ b/platforms/esp8266/src/main.cpp @@ -42,7 +42,7 @@ void run_wasm() printf("Running...\n"); - result = m3_CallVariadic(f, 1, 24); + result = m3_CallV(f, 24); if (result) FATAL("m3_Call: %s", result); long value = *(uint64_t*)(runtime->stack); diff --git a/platforms/fomu/src/main.c b/platforms/fomu/src/main.c index 2f60ba7..e59d5af 100644 --- a/platforms/fomu/src/main.c +++ b/platforms/fomu/src/main.c @@ -72,7 +72,7 @@ bool run_wasm() uart_print("Running...\n"); - result = m3_CallVariadic(f, 1, 24); + result = m3_CallV (f, 24); if (result) FATAL("m3_Call: %s", result); long value = *(uint64_t*)(runtime->stack); diff --git a/platforms/hifive1/src/main.c b/platforms/hifive1/src/main.c index 97e9efc..f307052 100644 --- a/platforms/hifive1/src/main.c +++ b/platforms/hifive1/src/main.c @@ -41,7 +41,7 @@ void run_wasm() printf("Running...\n"); - result = m3_CallVariadic(f, 1, 24); + result = m3_CallV (f, 24); if (result) FATAL("m3_Call: %s", result); long value = *(uint64_t*)(runtime->stack); diff --git a/platforms/ios/wasm3/main.c b/platforms/ios/wasm3/main.c index a0c5e62..1c26ffb 100644 --- a/platforms/ios/wasm3/main.c +++ b/platforms/ios/wasm3/main.c @@ -81,10 +81,10 @@ void run_wasm() const char* i_argv[2] = { FIB_ARG_VALUE, NULL }; clock_t start = clock(); - result = m3_CallWithArgs (f, 1, i_argv); + result = m3_CallArgV (f, 1, i_argv); clock_t end = clock(); - if (result) FATAL("m3_CallWithArgs: %s", result); + if (result) FATAL("m3_Call: %s", result); printf("Elapsed: %ld ms\n\n", (end - start) * 1000 / CLOCKS_PER_SEC); // uint64_t value = *(uint64_t*)(runtime->stack); diff --git a/platforms/python/m3module.c b/platforms/python/m3module.c index cc3ed60..25db331 100644 --- a/platforms/python/m3module.c +++ b/platforms/python/m3module.c @@ -1,8 +1,8 @@ #include "Python.h" -#include "m3_api_defs.h" #include "wasm3.h" -/* FIXME: remove when there is a public API to get function return value */ +#include "m3_api_defs.h" +/* FIXME: remove when there is a public API to get module/function names */ #include "m3_env.h" #define MAX_ARGS 32 @@ -153,7 +153,7 @@ static PyType_Slot M3_Runtime_Type_slots[] = { static PyObject* Module_name(m3_module *self, void * closure) { - return PyUnicode_FromString(self->m->name); + return PyUnicode_FromString(self->m->name); // TODO } static PyGetSetDef M3_Module_properties[] = { @@ -182,18 +182,44 @@ put_arg_on_stack(u64 *s, M3ValueType type, PyObject *arg) } static PyObject * -get_result_from_stack(IM3FuncType ftype, m3stack_t stack) +get_result_from_stack(IM3Function f) { - u8 type = GetSingleRetType(ftype); + int nRets = m3_GetRetCount(f); + if (nRets <= 0) { + Py_RETURN_NONE; + } + + if (nRets > 1) { + return PyErr_Format(PyExc_TypeError, "multi-value not supported yet"); + } + + if (nRets > MAX_ARGS) { + return PyErr_Format(PyExc_TypeError, "too many rets"); + } + + static uint64_t valbuff[MAX_ARGS]; + static const void* valptrs[MAX_ARGS]; + memset(valbuff, 0, sizeof(valbuff)); + memset(valptrs, 0, sizeof(valptrs)); + + for (int i = 0; i < nRets; i++) { + valptrs[i] = &valbuff[i]; + } + M3Result res = m3_GetResults (f, nRets, valptrs); + if (res) { + return PyErr_Format(PyExc_TypeError, "Error: %s", res); + } + + int i = 0; + u8 type = m3_GetRetType(f, i); switch (type) { - case c_m3Type_none: Py_RETURN_NONE; - case c_m3Type_i32: return PyLong_FromLong(*(i32*)(stack)); - case c_m3Type_i64: return PyLong_FromLong(*(i64*)(stack)); - case c_m3Type_f32: return PyFloat_FromDouble(*(f32*)(stack)); - case c_m3Type_f64: return PyFloat_FromDouble(*(f64*)(stack)); + case c_m3Type_i32: return PyLong_FromLong( *(i32*)valptrs[i]); break; + case c_m3Type_i64: return PyLong_FromLong( *(i64*)valptrs[i]); break; + case c_m3Type_f32: return PyFloat_FromDouble(*(f32*)valptrs[i]); break; + case c_m3Type_f64: return PyFloat_FromDouble(*(f64*)valptrs[i]); break; default: return PyErr_Format(PyExc_TypeError, "unknown return type %d", (int)type); - } + } } static PyObject * @@ -204,13 +230,13 @@ M3_Function_call_argv(m3_function *func, PyObject *args) for(i = 0; i< size;++i) { argv[i] = PyUnicode_AsUTF8(PyTuple_GET_ITEM(args, i)); } - M3Result res = m3_CallWithArgs(func->f, size, argv); + M3Result res = m3_CallArgV(func->f, size, argv); if (res) { return PyErr_Format(PyExc_TypeError, "Error: %s", res); } - return get_result_from_stack(func->f->funcType, func->r->stack); + return get_result_from_stack(func->f); } static PyObject* @@ -219,36 +245,36 @@ M3_Function_call(m3_function *self, PyObject *args, PyObject *kwargs) u32 i; IM3Function f = self->f; - unsigned nArgs = m3_GetArgCount(f); + int nArgs = m3_GetArgCount(f); if (nArgs > MAX_ARGS) { return PyErr_Format(PyExc_TypeError, "too many args"); } - static uint64_t argsbuf[MAX_ARGS]; - static const void* argptrs[MAX_ARGS]; - memset(argsbuf, 0, sizeof(args)); - memset(argptrs, 0, sizeof(argptrs)); + static uint64_t valbuff[MAX_ARGS]; + static const void* valptrs[MAX_ARGS]; + memset(valbuff, 0, sizeof(args)); + memset(valptrs, 0, sizeof(valptrs)); - for (unsigned i = 0; i < nArgs; i++) { - u64* s = &argsbuf[i]; - argptrs[i] = s; + for (int i = 0; i < nArgs; i++) { + u64* s = &valbuff[i]; + valptrs[i] = s; put_arg_on_stack(s, m3_GetArgType(f, i), PyTuple_GET_ITEM(args, i)); } - M3Result res = m3_Call (f, nArgs, argptrs); + M3Result res = m3_Call (f, nArgs, valptrs); if (res) { return PyErr_Format(PyExc_TypeError, "Error: %s", res); } - return get_result_from_stack(f->funcType, self->r->stack); + return get_result_from_stack(f); } static PyObject* Function_name(m3_function *self, void * closure) { - return PyUnicode_FromString(self->f->name); + return PyUnicode_FromString(self->f->name); // TODO } static PyObject* @@ -258,9 +284,9 @@ Function_num_args(m3_function *self, void * closure) } static PyObject* -Function_return_type(m3_function *self, void * closure) +Function_num_rets(m3_function *self, void * closure) { - return PyLong_FromLong(GetSingleRetType(self->f->funcType)); + return PyLong_FromLong(m3_GetRetCount(self->f)); } static PyObject* @@ -277,11 +303,26 @@ Function_arg_types(m3_function *self, void * closure) return ret; } +static PyObject* +Function_ret_types(m3_function *self, void * closure) +{ + Py_ssize_t nRets = m3_GetRetCount(self->f); + PyObject *ret = PyTuple_New(nRets); + if (ret) { + Py_ssize_t i; + for (i = 0; i < nRets; ++i) { + PyTuple_SET_ITEM(ret, i, PyLong_FromLong(m3_GetRetType(self->f, i))); + } + } + return ret; +} + static PyGetSetDef M3_Function_properties[] = { {"name", (getter) Function_name, NULL, "function name", NULL }, {"num_args", (getter) Function_num_args, NULL, "number of args", NULL }, - {"return_type", (getter) Function_return_type, NULL, "return type", NULL }, + {"num_rets", (getter) Function_num_rets, NULL, "number of rets", NULL }, {"arg_types", (getter) Function_arg_types, NULL, "types of args", NULL }, + {"ret_types", (getter) Function_ret_types, NULL, "types of rets", NULL }, {NULL} /* Sentinel */ }; diff --git a/platforms/python/test/test_m3.py b/platforms/python/test/test_m3.py index c9b3289..9302b9b 100644 --- a/platforms/python/test/test_m3.py +++ b/platforms/python/test/test_m3.py @@ -54,8 +54,9 @@ def test_m3(capfd): assert func.call_argv('10') == 55 assert func.name == 'fib' assert func.num_args == 1 - assert func.return_type == 1 + assert func.num_rets == 1 assert func.arg_types == (1,) + assert func.ret_types == (1,) assert func(0) == 0 assert func(1) == 1 rt.load(env.parse_module(ADD_WASM)) diff --git a/platforms/wm_w600/main.c b/platforms/wm_w600/main.c index e397432..f6b82dd 100644 --- a/platforms/wm_w600/main.c +++ b/platforms/wm_w600/main.c @@ -46,10 +46,9 @@ void run_wasm() printf("Running...\n"); - const char* i_argv[2] = { "24", NULL }; - result = m3_CallWithArgs (f, 1, i_argv); + result = m3_CallV (f, 24); - if (result) FATAL("m3_CallWithArgs: %s", result); + if (result) FATAL("m3_Call: %s", result); //long value = *(uint64_t*)(runtime->stack); //printf("Result: %ld\n", value); diff --git a/source/m3_api_tracer.c b/source/m3_api_tracer.c index 8e35fbe..fb4a185 100644 --- a/source/m3_api_tracer.c +++ b/source/m3_api_tracer.c @@ -83,10 +83,10 @@ d_m3TraceMemory( load_val_i32, "load i32", int32_t, "%" PRIi32) d_m3TraceMemory(store_val_i32, "store i32", int32_t, "%" PRIi32) d_m3TraceMemory( load_val_i64, "load i64", int64_t, "%" PRIi64) d_m3TraceMemory(store_val_i64, "store i64", int64_t, "%" PRIi64) -d_m3TraceMemory( load_val_f32, "load f32", float, "%f") -d_m3TraceMemory(store_val_f32, "store f32", float, "%f") -d_m3TraceMemory( load_val_f64, "load f64", double, "%lf") -d_m3TraceMemory(store_val_f64, "store f64", double, "%lf") +d_m3TraceMemory( load_val_f32, "load f32", float, "%" PRIf32) +d_m3TraceMemory(store_val_f32, "store f32", float, "%" PRIf32) +d_m3TraceMemory( load_val_f64, "load f64", double, "%" PRIf64) +d_m3TraceMemory(store_val_f64, "store f64", double, "%" PRIf64) #define d_m3TraceLocal(FUNC, NAME, TYPE, FMT) \ @@ -105,10 +105,10 @@ d_m3TraceLocal(get_i32, "get i32", int32_t, "%" PRIi32) d_m3TraceLocal(set_i32, "set i32", int32_t, "%" PRIi32) d_m3TraceLocal(get_i64, "get i64", int64_t, "%" PRIi64) d_m3TraceLocal(set_i64, "set i64", int64_t, "%" PRIi64) -d_m3TraceLocal(get_f32, "get f32", float, "%f") -d_m3TraceLocal(set_f32, "set f32", float, "%f") -d_m3TraceLocal(get_f64, "get f64", double, "%lf") -d_m3TraceLocal(set_f64, "set f64", double, "%lf") +d_m3TraceLocal(get_f32, "get f32", float, "%" PRIf32) +d_m3TraceLocal(set_f32, "set f32", float, "%" PRIf32) +d_m3TraceLocal(get_f64, "get f64", double, "%" PRIf64) +d_m3TraceLocal(set_f64, "set f64", double, "%" PRIf64) static diff --git a/source/m3_compile.c b/source/m3_compile.c index 80d44a9..55504c1 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -938,7 +938,7 @@ M3Result Compile_Const_f32 (IM3Compilation o, m3opcode_t i_opcode) union { u32 u; f32 f; } value = { 0 }; -_ (Read_f32 (& value.f, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (const f32 = %f)", get_indention_string (o), value.f); +_ (Read_f32 (& value.f, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (const f32 = %" PRIf32 ")", get_indention_string (o), value.f); _ (PushConst (o, value.u, c_m3Type_f32)); _catch: return result; @@ -951,7 +951,7 @@ M3Result Compile_Const_f64 (IM3Compilation o, m3opcode_t i_opcode) union { u64 u; f64 f; } value = { 0 }; -_ (Read_f64 (& value.f, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (const f64 = %lf)", get_indention_string (o), value.f); +_ (Read_f64 (& value.f, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (const f64 = %" PRIf64 ")", get_indention_string (o), value.f); _ (PushConst (o, value.u, c_m3Type_f64)); _catch: return result; diff --git a/source/m3_core.h b/source/m3_core.h index a575de4..4b33667 100644 --- a/source/m3_core.h +++ b/source/m3_core.h @@ -43,6 +43,9 @@ typedef uint8_t u8; typedef int8_t i8; #endif // d_m3ShortTypesDefined +#define PRIf32 "f" +#define PRIf64 "lf" + typedef const void * m3ret_t; typedef const void * voidptr_t; typedef const char * cstr_t; diff --git a/source/m3_env.c b/source/m3_env.c index f2b6d7a..41460cc 100644 --- a/source/m3_env.c +++ b/source/m3_env.c @@ -781,113 +781,180 @@ M3ValueType m3_GetRetType (IM3Function i_function, uint32_t index) return c_m3Type_none; } -M3Result m3_CallVariadic (IM3Function i_function, uint32_t i_argc, ...) +M3Result m3_CallV (IM3Function i_function, ...) { va_list ap; - va_start(ap, i_argc); - M3Result r = m3_CallWithVaList(i_function, i_argc, ap); + va_start(ap, i_function); + M3Result r = m3_CallVL(i_function, ap); va_end(ap); return r; } -M3Result m3_CallWithVaList (IM3Function i_function, uint32_t i_argc, va_list i_args) +M3Result m3_CallVL (IM3Function i_function, va_list i_args) { + IM3Runtime runtime = i_function->module->runtime; IM3FuncType ftype = i_function->funcType; - if (i_argc != ftype->numArgs) { - return m3Err_argumentCountMismatch; - } + if (!i_function->compiled) { return m3Err_missingCompiledCode; } - IM3Runtime runtime = i_function->module->runtime; - - // args are always 64-bit aligned - u64* stack = (u64*) runtime->stack; + u8* s = (u8*) runtime->stack; for (u32 i = 0; i < ftype->numArgs; ++i) { - u64* s = & stack[i]; switch (d_FuncArgType(ftype, i)) { - case c_m3Type_i32: *(i32*)(s) = va_arg(i_args, i32); break; - case c_m3Type_i64: *(i64*)(s) = va_arg(i_args, i64); break; - case c_m3Type_f32: *(f32*)(s) = va_arg(i_args, f64); break; // f32 is passed as f64 - case c_m3Type_f64: *(f64*)(s) = va_arg(i_args, f64); break; + case c_m3Type_i32: *(i32*)(s) = va_arg(i_args, i32); s += 8; break; + case c_m3Type_i64: *(i64*)(s) = va_arg(i_args, i64); s += 8; break; + case c_m3Type_f32: *(f32*)(s) = va_arg(i_args, f64); s += 8; break; // f32 is passed as f64 + case c_m3Type_f64: *(f64*)(s) = va_arg(i_args, f64); s += 8; break; default: return "unknown argument type"; } } m3StackCheckInit(); - return (M3Result) Call (i_function->compiled, (m3stack_t) stack, runtime->memory.mallocated, d_m3OpDefaultArgs); + M3Result r = (M3Result) Call (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); + + runtime->lastCalled = r ? NULL : i_function; + +#if d_m3LogNativeStack + int stackUsed = m3StackGetMax(); + fprintf (stderr, "Native stack used: %d\n", stackUsed); +#endif + + return r; } M3Result m3_Call (IM3Function i_function, uint32_t i_argc, const void * i_argptrs[]) { + IM3Runtime runtime = i_function->module->runtime; IM3FuncType ftype = i_function->funcType; + if (i_argc != ftype->numArgs) { return m3Err_argumentCountMismatch; } if (!i_function->compiled) { return m3Err_missingCompiledCode; } - IM3Runtime runtime = i_function->module->runtime; - - // args are always 64-bit aligned - u64* stack = (u64*) runtime->stack; + u8* s = (u8*) runtime->stack; for (u32 i = 0; i < ftype->numArgs; ++i) { - u64* s = & stack[i]; - switch (d_FuncArgType(ftype, i)) { - case c_m3Type_i32: *(i32*)(s) = *(i32*)i_argptrs[i]; break; - case c_m3Type_i64: *(i64*)(s) = *(i64*)i_argptrs[i]; break; - case c_m3Type_f32: *(f32*)(s) = *(f32*)i_argptrs[i]; break; - case c_m3Type_f64: *(f64*)(s) = *(f64*)i_argptrs[i]; break; + case c_m3Type_i32: *(i32*)(s) = *(i32*)i_argptrs[i]; s += 8; break; + case c_m3Type_i64: *(i64*)(s) = *(i64*)i_argptrs[i]; s += 8; break; + case c_m3Type_f32: *(f32*)(s) = *(f32*)i_argptrs[i]; s += 8; break; + case c_m3Type_f64: *(f64*)(s) = *(f64*)i_argptrs[i]; s += 8; break; default: return "unknown argument type"; } } m3StackCheckInit(); - return (M3Result) Call (i_function->compiled, (m3stack_t) stack, runtime->memory.mallocated, d_m3OpDefaultArgs); + M3Result r = (M3Result) Call (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); + + runtime->lastCalled = r ? NULL : i_function; + +#if d_m3LogNativeStack + int stackUsed = m3StackGetMax(); + fprintf (stderr, "Native stack used: %d\n", stackUsed); +#endif + + return r; } -M3Result m3_CallWithArgs (IM3Function i_function, uint32_t i_argc, const char * i_argv[]) +M3Result m3_CallArgV (IM3Function i_function, uint32_t i_argc, const char * i_argv[]) { IM3FuncType ftype = i_function->funcType; + IM3Runtime runtime = i_function->module->runtime; + if (i_argc != ftype->numArgs) { return m3Err_argumentCountMismatch; } if (!i_function->compiled) { return m3Err_missingCompiledCode; } - IM3Runtime runtime = i_function->module->runtime; - - // args are always 64-bit aligned - u64* stack = (u64*) runtime->stack; + u8* s = (u8*) runtime->stack; for (u32 i = 0; i < ftype->numArgs; ++i) { - u64* s = & stack[i]; - switch (d_FuncArgType(ftype, i)) { - case c_m3Type_i32: *(i32*)(s) = strtoul(i_argv[i], NULL, 10); break; - case c_m3Type_i64: *(i64*)(s) = strtoull(i_argv[i], NULL, 10); break; - case c_m3Type_f32: *(f32*)(s) = strtod(i_argv[i], NULL); break; - case c_m3Type_f64: *(f64*)(s) = strtod(i_argv[i], NULL); break; + case c_m3Type_i32: *(i32*)(s) = strtoul(i_argv[i], NULL, 10); s += 8; break; + case c_m3Type_i64: *(i64*)(s) = strtoull(i_argv[i], NULL, 10); s += 8; break; + case c_m3Type_f32: *(f32*)(s) = strtod(i_argv[i], NULL); s += 8; break; // strtof would be less portable + case c_m3Type_f64: *(f64*)(s) = strtod(i_argv[i], NULL); s += 8; break; default: return "unknown argument type"; } } m3StackCheckInit(); - M3Result r = (M3Result) Call (i_function->compiled, (m3stack_t) stack, runtime->memory.mallocated, d_m3OpDefaultArgs); + M3Result r = (M3Result) Call (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); + + runtime->lastCalled = r ? NULL : i_function; #if d_m3LogNativeStack int stackUsed = m3StackGetMax(); fprintf (stderr, "Native stack used: %d\n", stackUsed); -#endif // d_m3LogNativeStack +#endif return r; } +M3Result m3_GetResults (IM3Function i_function, uint32_t i_retc, const void * o_retptrs[]) +{ + IM3FuncType ftype = i_function->funcType; + IM3Runtime runtime = i_function->module->runtime; + + if (i_retc != ftype->numRets) { + return m3Err_argumentCountMismatch; + } + if (i_function != runtime->lastCalled) { + return "function not called"; + } + + u8* s = (u8*) runtime->stack; + for (u32 i = 0; i < ftype->numRets; ++i) + { + switch (d_FuncRetType(ftype, i)) { + case c_m3Type_i32: *(i32*)o_retptrs[i] = *(i32*)(s); s += 8; break; + case c_m3Type_i64: *(i64*)o_retptrs[i] = *(i64*)(s); s += 8; break; + case c_m3Type_f32: *(f32*)o_retptrs[i] = *(f32*)(s); s += 8; break; + case c_m3Type_f64: *(f64*)o_retptrs[i] = *(f64*)(s); s += 8; break; + default: return "unknown return type"; + } + } + return m3Err_none; +} + +M3Result m3_GetResultsV (IM3Function i_function, ...) +{ + va_list ap; + va_start(ap, i_function); + M3Result r = m3_GetResultsVL(i_function, ap); + va_end(ap); + return r; +} + +M3Result m3_GetResultsVL (IM3Function i_function, va_list o_rets) +{ + IM3Runtime runtime = i_function->module->runtime; + IM3FuncType ftype = i_function->funcType; + + if (i_function != runtime->lastCalled) { + return "function not called"; + } + + u8* s = (u8*) runtime->stack; + for (u32 i = 0; i < ftype->numRets; ++i) + { + switch (d_FuncRetType(ftype, i)) { + case c_m3Type_i32: *va_arg(o_rets, i32*) = *(i32*)(s); s += 8; break; + case c_m3Type_i64: *va_arg(o_rets, i64*) = *(i64*)(s); s += 8; break; + case c_m3Type_f32: *va_arg(o_rets, f32*) = *(f32*)(s); s += 8; break; + case c_m3Type_f64: *va_arg(o_rets, f64*) = *(f64*)(s); s += 8; break; + default: return "unknown argument type"; + } + } + return m3Err_none; +} + void ReleaseCodePageNoTrack (IM3Runtime i_runtime, IM3CodePage i_codePage) { if (i_codePage) @@ -978,9 +1045,9 @@ M3Result m3Error (M3Result i_result, IM3Runtime i_runtime, IM3Module i_module, #endif -void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* info) +void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* o_info) { - *info = i_runtime->error; + *o_info = i_runtime->error; m3_ResetErrorInfo (i_runtime); } diff --git a/source/m3_env.h b/source/m3_env.h index fa58593..d4c5d49 100644 --- a/source/m3_env.h +++ b/source/m3_env.h @@ -218,6 +218,7 @@ typedef struct M3Runtime void * stack; u32 stackSize; u32 numStackSlots; + IM3Function lastCalled; // last function that successfully executed void * userdata; diff --git a/source/m3_exec.h b/source/m3_exec.h index 729be99..a70fe8b 100644 --- a/source/m3_exec.h +++ b/source/m3_exec.h @@ -558,10 +558,10 @@ d_m3Op (CallRawFunction) for (int i=0; itypes[nRets + i]; switch (type) { - case c_m3Type_i32: outp += snprintf(outp, oute-outp, "%i", *(i32*)(sp+i)); break; - case c_m3Type_i64: outp += snprintf(outp, oute-outp, "%lli", *(i64*)(sp+i)); break; - case c_m3Type_f32: outp += snprintf(outp, oute-outp, "%f", *(f32*)(sp+i)); break; - case c_m3Type_f64: outp += snprintf(outp, oute-outp, "%lf", *(f64*)(sp+i)); break; + case c_m3Type_i32: outp += snprintf(outp, oute-outp, "%" PRIi32, *(i32*)(sp+i)); break; + case c_m3Type_i64: outp += snprintf(outp, oute-outp, "%" PRIi64, *(i64*)(sp+i)); break; + case c_m3Type_f32: outp += snprintf(outp, oute-outp, "%" PRIf32, *(f32*)(sp+i)); break; + case c_m3Type_f64: outp += snprintf(outp, oute-outp, "%" PRIf64, *(f64*)(sp+i)); break; default: outp += snprintf(outp, oute-outp, "", type); break; } outp += snprintf(outp, oute-outp, (i < nArgs-1) ? ", " : ")"); @@ -576,10 +576,10 @@ d_m3Op (CallRawFunction) } else { switch (GetSingleRetType(ftype)) { case c_m3Type_none: fprintf(out, "%s\n", outbuff); break; - case c_m3Type_i32: fprintf(out, "%s = %i\n", outbuff, *(i32*)sp); break; - case c_m3Type_i64: fprintf(out, "%s = %lli\n", outbuff, *(i64*)sp); break; - case c_m3Type_f32: fprintf(out, "%s = %f\n", outbuff, *(f32*)sp); break; - case c_m3Type_f64: fprintf(out, "%s = %lf\n", outbuff, *(f64*)sp); break; + case c_m3Type_i32: fprintf(out, "%s = %" PRIi32 "\n", outbuff, *(i32*)sp); break; + case c_m3Type_i64: fprintf(out, "%s = %" PRIi64 "\n", outbuff, *(i64*)sp); break; + case c_m3Type_f32: fprintf(out, "%s = %" PRIf32 "\n", outbuff, *(f32*)sp); break; + case c_m3Type_f64: fprintf(out, "%s = %" PRIf64 "\n", outbuff, *(f64*)sp); break; } } #endif @@ -861,8 +861,9 @@ d_m3Op (DumpStack) printf (" %4d ", opcodeIndex); printf (" %-25s r0: 0x%016" PRIx64 " i:%" PRIi64 " u:%" PRIu64 "\n", funcName, _r0, _r0, _r0); - printf (" fp0: %lf\n", _fp0); - +#if d_m3HasFloat + printf (" fp0: %" PRIf64 "\n", _fp0); +#endif m3stack_t sp = _sp; for (u32 i = 0; i < stackHeight; ++i) diff --git a/source/m3_info.c b/source/m3_info.c index 7f18ed8..3e38b72 100644 --- a/source/m3_info.c +++ b/source/m3_info.c @@ -100,9 +100,9 @@ size_t SPrintArg (char * o_string, size_t i_n, m3stack_t i_sp, u8 i_type) len = snprintf (o_string, i_n, "%" PRIi64, * (i64 *) i_sp); #if d_m3HasFloat else if (i_type == c_m3Type_f32) - len = snprintf (o_string, i_n, "%f", * (f32 *) i_sp); + len = snprintf (o_string, i_n, "%" PRIf32, * (f32 *) i_sp); else if (i_type == c_m3Type_f64) - len = snprintf (o_string, i_n, "%lf", * (f64 *) i_sp); + len = snprintf (o_string, i_n, "%" PRIf64, * (f64 *) i_sp); #endif len = M3_MAX (0, len); diff --git a/source/wasm3.h b/source/wasm3.h index 0af506c..792734e 100644 --- a/source/wasm3.h +++ b/source/wasm3.h @@ -208,17 +208,21 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") uint32_t m3_GetArgCount (IM3Function i_function); uint32_t m3_GetRetCount (IM3Function i_function); - M3ValueType m3_GetArgType (IM3Function i_function, uint32_t index); - M3ValueType m3_GetRetType (IM3Function i_function, uint32_t index); + M3ValueType m3_GetArgType (IM3Function i_function, uint32_t i_index); + M3ValueType m3_GetRetType (IM3Function i_function, uint32_t i_index); - M3Result m3_CallVariadic (IM3Function i_function, uint32_t i_argc, ...); - M3Result m3_CallWithVaList (IM3Function i_function, uint32_t i_argc, va_list i_args); + M3Result m3_CallV (IM3Function i_function, ...); + M3Result m3_CallVL (IM3Function i_function, va_list i_args); M3Result m3_Call (IM3Function i_function, uint32_t i_argc, const void * i_argptrs[]); - M3Result m3_CallWithArgs (IM3Function i_function, uint32_t i_argc, const char * i_argv[]); + M3Result m3_CallArgV (IM3Function i_function, uint32_t i_argc, const char * i_argv[]); + + M3Result m3_GetResultsV (IM3Function i_function, ...); + M3Result m3_GetResultsVL (IM3Function i_function, va_list o_rets); + M3Result m3_GetResults (IM3Function i_function, uint32_t i_retc, const void * o_retptrs[]); // IM3Functions are valid during the lifetime of the originating runtime - void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* info); + void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* o_info); void m3_ResetErrorInfo (IM3Runtime i_runtime); //-------------------------------------------------------------------------------------------------------------------------------