Basic stack access API. Closes #41

extensions
Volodymyr Shymanskyy 3 years ago
parent 23ccccb9f8
commit d71a204e55

@ -10,7 +10,6 @@
#include <time.h>
#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);

@ -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: <Empty Stack>\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: <Empty Stack>\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;

@ -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);
}
}

@ -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);

@ -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);

@ -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 */

@ -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);

@ -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);

@ -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);

@ -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);

@ -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);

@ -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);

@ -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);

@ -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);

@ -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);

@ -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 */
};

@ -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))

@ -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);

@ -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

@ -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;

@ -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;

@ -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);
}

@ -218,6 +218,7 @@ typedef struct M3Runtime
void * stack;
u32 stackSize;
u32 numStackSlots;
IM3Function lastCalled; // last function that successfully executed
void * userdata;

@ -558,10 +558,10 @@ d_m3Op (CallRawFunction)
for (int i=0; i<nArgs; i++) {
const int type = ftype->types[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, "<unknown type %d>", 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)

@ -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);

@ -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);
//-------------------------------------------------------------------------------------------------------------------------------

Loading…
Cancel
Save