You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wasm3/source/m3_bind.c

196 lines
5.5 KiB
C

//
// m3_bind.c
//
// Created by Steven Massey on 4/29/19.
// Copyright © 2019 Steven Massey. All rights reserved.
//
#include "m3_exec.h"
#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)
{
M3Result result = m3Err_none;
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;
int maxNumArgs = strlen (i_signature) - 2; // "()"
_throwif (m3Err_malformedFunctionSignature, maxNumArgs < 0);
_throwif ("insane argument count", maxNumArgs > d_m3MaxSaneFunctionArgCount);
const unsigned umaxNumArgs = (unsigned)maxNumArgs;
_ (AllocFuncType (& funcType, umaxNumArgs));
bool parsingArgs = false;
while (* sig)
{
char typeChar = * sig++;
if (typeChar == '(')
{
parsingArgs = true;
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 (not parsingArgs)
{
_throwif ("malformed function signature; too many return types", funcType->numRets >= 1);
d_FuncRetType(funcType, funcType->numRets++) = type;
}
else
{
_throwif (m3Err_malformedFunctionSignature, funcType->numArgs >= umaxNumArgs); // forgot trailing ')' ?
d_FuncArgType(funcType, funcType->numArgs++) = type;
}
}
} _catch:
if (result)
m3Free (funcType); // nulls 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:
m3Free (ftype);
return result;
}
M3Result LinkRawFunction (IM3Module io_module, IM3Function io_function, ccstr_t signature, const void * i_function, const void * i_userdata)
{
M3Result result = m3Err_none; d_m3Assert (io_module->runtime);
_try {
_ (ValidateSignature (io_function, signature));
IM3CodePage page = AcquireCodePageWithCapacity (io_module->runtime, 4);
if (page)
{
io_function->compiled = GetPagePC (page);
io_function->module = io_module;
EmitWord (page, op_CallRawFunction);
EmitWord (page, i_function);
EmitWord (page, io_function);
EmitWord (page, i_userdata);
ReleaseCodePage (io_module->runtime, page);
}
else _throw(m3Err_mallocFailedCodePage);
} _catch:
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)
{
M3Result result = m3Err_functionLookupFailed;
bool wildcardModule = (strcmp (i_moduleName, "*") == 0);
for (u32 i = 0; i < io_module->numFunctions; ++i)
{
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))
{
result = LinkRawFunction (io_module, f, i_signature, i_function, i_userdata);
if (result) return result;
}
}
}
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);
}