orca/ext/wasm3/source/m3_bind.c

176 lines
4.8 KiB
C

//
// m3_bind.c
//
// Created by Steven Massey on 4/29/19.
// Copyright © 2019 Steven Massey. All rights reserved.
//
#include "m3_env.h"
#include "m3_exception.h"
#include "m3_info.h"
u8 ConvertTypeCharToTypeId (char i_code)
{
switch (i_code) {
case 'v': return c_m3Type_none;
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_i32;
}
return c_m3Type_unknown;
}
M3Result SignatureToFuncType (IM3FuncType * o_functionType, ccstr_t i_signature)
{
IM3FuncType funcType = NULL;
_try {
if (not o_functionType)
_throw ("null function type");
if (not i_signature)
_throw ("null function signature");
cstr_t sig = i_signature;
size_t maxNumTypes = strlen (i_signature);
// assume min signature is "()"
_throwif (m3Err_malformedFunctionSignature, maxNumTypes < 2);
maxNumTypes -= 2;
_throwif (m3Err_tooManyArgsRets, maxNumTypes > d_m3MaxSaneFunctionArgRetCount);
_ (AllocFuncType (& funcType, (u32) maxNumTypes));
u8 * typelist = funcType->types;
bool parsingRets = true;
while (* sig)
{
char typeChar = * sig++;
if (typeChar == '(')
{
parsingRets = false;
continue;
}
else if ( typeChar == ' ')
continue;
else if (typeChar == ')')
break;
u8 type = ConvertTypeCharToTypeId (typeChar);
_throwif ("unknown argument type char", c_m3Type_unknown == type);
if (type == c_m3Type_none)
continue;
if (parsingRets)
{
_throwif ("malformed signature; return count overflow", funcType->numRets >= maxNumTypes);
funcType->numRets++;
*typelist++ = type;
}
else
{
_throwif ("malformed signature; arg count overflow", (u32)(funcType->numRets) + funcType->numArgs >= maxNumTypes);
funcType->numArgs++;
*typelist++ = type;
}
}
} _catch:
if (result)
m3_Free (funcType);
* o_functionType = funcType;
return result;
}
static
M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature)
{
M3Result result = m3Err_none;
IM3FuncType ftype = NULL;
_ (SignatureToFuncType (& ftype, i_linkingSignature));
if (not AreFuncTypesEqual (ftype, i_function->funcType))
{
m3log (module, "expected: %s", SPrintFuncTypeSignature (ftype));
m3log (module, " found: %s", SPrintFuncTypeSignature (i_function->funcType));
_throw ("function signature mismatch");
}
_catch:
m3_Free (ftype);
return result;
}
M3Result FindAndLinkFunction (IM3Module io_module,
ccstr_t i_moduleName,
ccstr_t i_functionName,
ccstr_t i_signature,
voidptr_t i_function,
voidptr_t i_userdata)
{
_try {
_throwif(m3Err_moduleNotLinked, !io_module->runtime);
const bool wildcardModule = (strcmp (i_moduleName, "*") == 0);
result = m3Err_functionLookupFailed;
for (u32 i = 0; i < io_module->numFunctions; ++i)
{
const IM3Function f = & io_module->functions [i];
if (f->import.moduleUtf8 and f->import.fieldUtf8)
{
if (strcmp (f->import.fieldUtf8, i_functionName) == 0 and
(wildcardModule or strcmp (f->import.moduleUtf8, i_moduleName) == 0))
{
if (i_signature) {
_ (ValidateSignature (f, i_signature));
}
_ (CompileRawFunction (io_module, f, i_function, i_userdata));
}
}
}
} _catch:
return result;
}
M3Result m3_LinkRawFunctionEx (IM3Module io_module,
const char * const i_moduleName,
const char * const i_functionName,
const char * const i_signature,
M3RawCall i_function,
const void * i_userdata)
{
return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, (voidptr_t)i_function, i_userdata);
}
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, i_signature, (voidptr_t)i_function, NULL);
}