|
|
@ -781,113 +781,180 @@ M3ValueType m3_GetRetType (IM3Function i_function, uint32_t index)
|
|
|
|
return c_m3Type_none;
|
|
|
|
return c_m3Type_none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
M3Result m3_CallVariadic (IM3Function i_function, uint32_t i_argc, ...)
|
|
|
|
M3Result m3_CallV (IM3Function i_function, ...)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, i_argc);
|
|
|
|
va_start(ap, i_function);
|
|
|
|
M3Result r = m3_CallWithVaList(i_function, i_argc, ap);
|
|
|
|
M3Result r = m3_CallVL(i_function, ap);
|
|
|
|
va_end(ap);
|
|
|
|
va_end(ap);
|
|
|
|
return r;
|
|
|
|
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;
|
|
|
|
IM3FuncType ftype = i_function->funcType;
|
|
|
|
if (i_argc != ftype->numArgs) {
|
|
|
|
|
|
|
|
return m3Err_argumentCountMismatch;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!i_function->compiled) {
|
|
|
|
if (!i_function->compiled) {
|
|
|
|
return m3Err_missingCompiledCode;
|
|
|
|
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)
|
|
|
|
for (u32 i = 0; i < ftype->numArgs; ++i)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
u64* s = & stack[i];
|
|
|
|
|
|
|
|
switch (d_FuncArgType(ftype, i)) {
|
|
|
|
switch (d_FuncArgType(ftype, i)) {
|
|
|
|
case c_m3Type_i32: *(i32*)(s) = va_arg(i_args, i32); 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); 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); break; // f32 is passed as f64
|
|
|
|
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); break;
|
|
|
|
case c_m3Type_f64: *(f64*)(s) = va_arg(i_args, f64); s += 8; break;
|
|
|
|
default: return "unknown argument type";
|
|
|
|
default: return "unknown argument type";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m3StackCheckInit();
|
|
|
|
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[])
|
|
|
|
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;
|
|
|
|
IM3FuncType ftype = i_function->funcType;
|
|
|
|
|
|
|
|
|
|
|
|
if (i_argc != ftype->numArgs) {
|
|
|
|
if (i_argc != ftype->numArgs) {
|
|
|
|
return m3Err_argumentCountMismatch;
|
|
|
|
return m3Err_argumentCountMismatch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!i_function->compiled) {
|
|
|
|
if (!i_function->compiled) {
|
|
|
|
return m3Err_missingCompiledCode;
|
|
|
|
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)
|
|
|
|
for (u32 i = 0; i < ftype->numArgs; ++i)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
u64* s = & stack[i];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (d_FuncArgType(ftype, i)) {
|
|
|
|
switch (d_FuncArgType(ftype, i)) {
|
|
|
|
case c_m3Type_i32: *(i32*)(s) = *(i32*)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]; break;
|
|
|
|
case c_m3Type_i64: *(i64*)(s) = *(i64*)i_argptrs[i]; s += 8; break;
|
|
|
|
case c_m3Type_f32: *(f32*)(s) = *(f32*)i_argptrs[i]; break;
|
|
|
|
case c_m3Type_f32: *(f32*)(s) = *(f32*)i_argptrs[i]; s += 8; break;
|
|
|
|
case c_m3Type_f64: *(f64*)(s) = *(f64*)i_argptrs[i]; break;
|
|
|
|
case c_m3Type_f64: *(f64*)(s) = *(f64*)i_argptrs[i]; s += 8; break;
|
|
|
|
default: return "unknown argument type";
|
|
|
|
default: return "unknown argument type";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m3StackCheckInit();
|
|
|
|
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;
|
|
|
|
IM3FuncType ftype = i_function->funcType;
|
|
|
|
|
|
|
|
IM3Runtime runtime = i_function->module->runtime;
|
|
|
|
|
|
|
|
|
|
|
|
if (i_argc != ftype->numArgs) {
|
|
|
|
if (i_argc != ftype->numArgs) {
|
|
|
|
return m3Err_argumentCountMismatch;
|
|
|
|
return m3Err_argumentCountMismatch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!i_function->compiled) {
|
|
|
|
if (!i_function->compiled) {
|
|
|
|
return m3Err_missingCompiledCode;
|
|
|
|
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)
|
|
|
|
for (u32 i = 0; i < ftype->numArgs; ++i)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
u64* s = & stack[i];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (d_FuncArgType(ftype, i)) {
|
|
|
|
switch (d_FuncArgType(ftype, i)) {
|
|
|
|
case c_m3Type_i32: *(i32*)(s) = strtoul(i_argv[i], NULL, 10); 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); 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); 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); break;
|
|
|
|
case c_m3Type_f64: *(f64*)(s) = strtod(i_argv[i], NULL); s += 8; break;
|
|
|
|
default: return "unknown argument type";
|
|
|
|
default: return "unknown argument type";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m3StackCheckInit();
|
|
|
|
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
|
|
|
|
#if d_m3LogNativeStack
|
|
|
|
int stackUsed = m3StackGetMax();
|
|
|
|
int stackUsed = m3StackGetMax();
|
|
|
|
fprintf (stderr, "Native stack used: %d\n", stackUsed);
|
|
|
|
fprintf (stderr, "Native stack used: %d\n", stackUsed);
|
|
|
|
#endif // d_m3LogNativeStack
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
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)
|
|
|
|
void ReleaseCodePageNoTrack (IM3Runtime i_runtime, IM3CodePage i_codePage)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (i_codePage)
|
|
|
|
if (i_codePage)
|
|
|
@ -978,9 +1045,9 @@ M3Result m3Error (M3Result i_result, IM3Runtime i_runtime, IM3Module i_module,
|
|
|
|
#endif
|
|
|
|
#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);
|
|
|
|
m3_ResetErrorInfo (i_runtime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|