176 lines
4.8 KiB
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);
|
||
|
}
|
||
|
|