refactoring / cleanup

extensions
Steven Massey 4 years ago
parent ab0c67868a
commit ad98bbd746

@ -0,0 +1,45 @@
//
// m3_test.c
// m3
//
// Created by Steven Massey on 2/27/20.
// Copyright © 2020 Steven Massey. All rights reserved.
//
#include <stdio.h>
#include "m3_ext.h"
#include "m3_bind.h"
#define Test(NAME) printf ("test: %s\n", #NAME);
#define expect(TEST) if (not (TEST)) { printf ("failed: (%s) on line: %d\n", #TEST, __LINE__); }
int main (int i_argc, const char * i_argv [])
{
Test (signatures)
{
M3Result result;
M3FuncType ftype = { 666, {}, 255 };
result = SignatureToFuncType (& ftype, ""); expect (result == m3Err_funcSignatureMissingReturnType)
result = SignatureToFuncType (& ftype, "()"); expect (result == m3Err_funcSignatureMissingReturnType)
result = SignatureToFuncType (& ftype, " v () "); expect (result == m3Err_none)
expect (ftype.returnType == c_m3Type_none)
expect (ftype.numArgs == 0)
result = SignatureToFuncType (& ftype, "f(IiF"); expect (result == m3Err_none)
expect (ftype.returnType == c_m3Type_f32)
expect (ftype.numArgs == 3)
M3FuncType ftype2;
result = SignatureToFuncType (& ftype2, "f(I i F)"); expect (result == m3Err_none);
expect (AreFuncTypesEqual (& ftype, &ftype2));
}
return 0;
}

@ -9,7 +9,7 @@
#include "m3_env.h"
#include "m3_exception.h"
static
u8 ConvertTypeCharToTypeId (char i_code)
{
switch (i_code) {
@ -23,30 +23,35 @@ u8 ConvertTypeCharToTypeId (char i_code)
return c_m3Type_none;
}
static
M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature)
M3Result SignatureToFuncType (M3FuncType * o_functionType, ccstr_t i_signature)
{
M3Result result = m3Err_none;
cstr_t sig = i_linkingSignature;
IM3FuncType bindType = i_function->funcType;
if (not o_functionType)
_throw ("null function type");
if (not i_signature)
_throw ("null function signature");
cstr_t sig = i_signature;
bool hasReturn = false;
u32 numArgs = 0;
o_functionType->numArgs = 0;
bool parsingArgs = false;
while (* sig)
{
if (numArgs >= d_m3MaxNumFunctionArgs)
_throw ("[link] arg count overflow");
if (o_functionType->numArgs >= d_m3MaxNumFunctionArgs)
_throw ("signature argument count overflow");
char typeChar = * sig++;
if (typeChar == '(')
{
if (not hasReturn)
_throw ("[link] malformed function signature; missing return type");
break;
parsingArgs = true;
continue;
}
@ -54,52 +59,59 @@ M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature
continue;
else if (typeChar == ')')
break;
u8 type = ConvertTypeCharToTypeId (typeChar);
if (type)
if (not type)
_throw ("unknown argument type char");
if (not parsingArgs)
{
if (not parsingArgs)
if (hasReturn)
_throw ("malformed function signature; too many return types");
hasReturn = true;
// M3FuncType doesn't speak 'void'
if (type == c_m3Type_void)
type = c_m3Type_none;
o_functionType->returnType = type;
}
else
{
if (type != c_m3Type_runtime)
{
if (hasReturn)
_throw ("[link] malformed function signature; too many return types");
hasReturn = true;
if (type == c_m3Type_ptr)
type = c_m3Type_i32;
// M3FuncType doesn't speak 'void'
if (type == c_m3Type_void)
type = c_m3Type_none;
if (type != bindType->returnType)
_throw ("[link] mismatch return type in linking function");
}
else
{
if (type != c_m3Type_runtime)
{
++numArgs;
if (numArgs <= bindType->numArgs)
{
if (type == c_m3Type_ptr)
type = c_m3Type_i32;
if (type != bindType->argTypes [numArgs - 1])
_throw ("[link] mismatched argument type");
}
else break;
}
o_functionType->argTypes [o_functionType->numArgs++] = type;
}
}
else _throw ("[link] unknown argument type char");
}
if (not hasReturn)
_throw (m3Err_funcSignatureMissingReturnType);
_catch: return result;
}
if (bindType->numArgs != numArgs)
_throw ("[link] function arg count mismatch");
static
M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature)
{
M3Result result = m3Err_none;
M3FuncType ftype;
_ (SignatureToFuncType (& ftype, i_linkingSignature));
if (not AreFuncTypesEqual (& ftype, i_function->funcType))
_throw ("function signature mismatch");
_catch: return result;
}
typedef M3Result (* M3Linker) (IM3Module io_module, IM3Function io_function, const char * const i_signature, const void * i_function);
M3Result FindAndLinkFunction (IM3Module io_module,

@ -0,0 +1,18 @@
//
// m3_bind.h
// m3
//
// Created by Steven Massey on 2/27/20.
// Copyright © 2020 Steven Massey. All rights reserved.
//
#ifndef m3_bind_h
#define m3_bind_h
#include "m3_core.h"
u8 ConvertTypeCharToTypeId (char i_code);
M3Result SignatureToFuncType (M3FuncType * o_functionType, ccstr_t i_signature);
#endif /* m3_bind_h */

@ -1339,8 +1339,7 @@ _ (ReadLEB_u32 (& typeIndex, & o->wasm, o->wasmEnd));
i8 reserved;
_ (ReadLEB_i7 (& reserved, & o->wasm, o->wasmEnd));
if (typeIndex >= o->module->numFuncTypes)
_throw ("function type index out of range");
_throwif ("function type index out of range", typeIndex >= o->module->numFuncTypes);
if (IsStackTopInRegister (o))
_ (PreserveRegisterIfOccupied (o, c_m3Type_i32));

@ -108,12 +108,10 @@ M3Result m3Malloc (void ** o_ptr, size_t i_size)
{
M3Result result = m3Err_none;
void * ptr = malloc (i_size);
if (ptr)
{
memset (ptr, 0x0, i_size);
}
else result = m3Err_mallocFailed;
void * ptr = calloc (i_size, 1);
if (not ptr)
result = m3Err_mallocFailed;
* o_ptr = ptr;
// printf("== alloc %d => %p\n", (u32) i_size, ptr);
@ -151,6 +149,22 @@ void * m3Realloc (void * i_ptr, size_t i_newSize, size_t i_oldSize)
return ptr;
}
M3Result m3MemCopy (void ** o_to, void * i_from, size_t i_size)
{
void * to = malloc (i_size);
if (to)
{
memcpy (to, i_from, i_size);
* o_to = to;
return m3Err_none;
}
else return m3Err_mallocFailed;
}
#endif
//--------------------------------------------------------------------------------------------

@ -210,7 +210,8 @@ void m3NotImplemented (void);
M3Result m3Malloc (void ** o_ptr, size_t i_size);
void * m3Realloc (void * i_ptr, size_t i_newSize, size_t i_oldSize);
void m3Free_impl (void * o_ptr);
void m3Free_impl (void * i_ptr);
M3Result m3MemCopy (void ** o_to, void * i_from, size_t i_size);
M3Result NormalizeType (u8 * o_type, i8 i_convolutedWasmType);

@ -12,6 +12,21 @@
#include "m3_exec.h"
#include "m3_exception.h"
bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB)
{
if (i_typeA->returnType == i_typeB->returnType)
{
if (i_typeA->numArgs == i_typeB->numArgs)
{
return (memcmp (i_typeA->argTypes, i_typeB->argTypes, i_typeA->numArgs) == 0);
}
}
return false;
}
cstr_t GetFunctionName (IM3Function i_function)
{
if (i_function->import.fieldUtf8)

@ -26,6 +26,7 @@ M3FuncType;
typedef M3FuncType * IM3FuncType;
void PrintFuncTypeSignature (IM3FuncType i_funcType);
bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB);
//---------------------------------------------------------------------------------------------------------------------------------
@ -38,6 +39,8 @@ typedef struct M3Function
bytes_t wasm;
bytes_t wasmEnd;
bool ownsWasmCode;
cstr_t name;
IM3FuncType funcType;
@ -56,8 +59,6 @@ typedef struct M3Function
u16 numConstantBytes;
void * constants;
// bool callNeedsRuntime;
}
M3Function;
@ -137,7 +138,7 @@ typedef M3Global * IM3Global;
//---------------------------------------------------------------------------------------------------------------------------------
typedef struct M3Module // TODO add env owner? also discriminates stack/heap
typedef struct M3Module
{
struct M3Runtime * runtime;
@ -170,8 +171,8 @@ typedef struct M3Module // TODO add env owner? also discriminate
M3MemoryInfo memoryInfo;
bool memoryImported;
// m3reg_t * globalMemory;
bool hasWasmCodeCopy;
struct M3Module * next;
}

@ -14,7 +14,8 @@
#define EXCEPTION_PRINT //puts("Exc: " __FILE__ ":" M3_STR(__LINE__) "\n");
#define _try
#define _(TRY) { result = TRY; if (result) { EXCEPTION_PRINT; goto _catch; } }
#define _throw(ERROR) { result = ERROR; EXCEPTION_PRINT; goto _catch; }
#define _(TRY) { result = TRY; if (result) { EXCEPTION_PRINT; goto _catch; } }
#define _throw(ERROR) { result = ERROR; EXCEPTION_PRINT; goto _catch; }
#define _throwif(ERROR, COND) if (COND) { result = ERROR; EXCEPTION_PRINT; goto _catch; }
#endif // m3_exception_h

@ -58,8 +58,7 @@ _ (m3Alloc (& io_module->funcTypes, M3FuncType, numTypes));
i8 form;
_ (ReadLEB_i7 (& form, & i_bytes, i_end));
if (form != -32)
_throw (m3Err_wasmMalformed); // for WA MVP }
_throwif (m3Err_wasmMalformed, form != -32); // for WA MVP
_ (ReadLEB_u32 (& ft->numArgs, & i_bytes, i_end));
@ -245,6 +244,7 @@ _ (ReadLEB_u32 (& startFuncIndex, & i_bytes, i_end));
_catch: return result;
}
M3Result Parse_InitExpr (M3Module * io_module, bytes_t * io_bytes, cbytes_t i_end)
{
M3Result result = m3Err_none;
@ -261,7 +261,6 @@ M3Result Parse_InitExpr (M3Module * io_module, bytes_t * io_bytes, cbytes_t i_
}
M3Result ParseSection_Element (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end)
{
M3Result result = m3Err_none;
@ -269,19 +268,16 @@ M3Result ParseSection_Element (IM3Module io_module, bytes_t i_bytes, cbytes_t
u32 numSegments;
result = ReadLEB_u32 (& numSegments, & i_bytes, i_end); m3log (parse, "** Element [%d]", numSegments);
if (not result)
{
io_module->elementSection = i_bytes;
io_module->elementSectionEnd = i_end;
io_module->numElementSegments = numSegments;
}
else result = "error parsing Element section";
_throwif ("error parsing Element section", result);
io_module->elementSection = i_bytes;
io_module->elementSectionEnd = i_end;
io_module->numElementSegments = numSegments;
return result;
_catch: return result;
}
M3Result ParseSection_Code (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end)
{
M3Result result;
@ -291,8 +287,7 @@ _ (ReadLEB_u32 (& numFunctions, & i_bytes, i_end));
if (numFunctions != io_module->numFunctions - io_module->numImports)
{
numFunctions = 0;
_throw (m3Err_wasmMalformed); // FIX: better error
_throw ("mismatched function count in code section");
}
for (u32 f = 0; f < numFunctions; ++f)
@ -332,6 +327,7 @@ _ (NormalizeType (& normalType, wasmType));
func->module = io_module;
func->wasm = start;
func->wasmEnd = i_bytes;
func->ownsWasmCode = io_module->hasWasmCodeCopy;
func->numLocals = numLocals;
}
else _throw (m3Err_wasmSectionOverrun);
@ -368,18 +364,15 @@ _ (ReadLEB_u32 (& segment->memoryRegion, & i_bytes, i_end));
_ (Parse_InitExpr (io_module, & i_bytes, i_end));
segment->initExprSize = (u32) (i_bytes - segment->initExpr);
if (segment->initExprSize <= 1)
_throw (m3Err_wasmMissingInitExpr);
_throwif (m3Err_wasmMissingInitExpr, segment->initExprSize <= 1);
_ (ReadLEB_u32 (& segment->size, & i_bytes, i_end));
segment->data = i_bytes; m3log (parse, " segment [%u] memory: %u; expr-size: %d; size: %d",
i, segment->memoryRegion, segment->initExprSize, segment->size);
i_bytes += segment->size;
}
_catch:
// TODO failure cleanup
return result;
}
@ -394,11 +387,9 @@ M3Result ParseSection_Memory (M3Module * io_module, bytes_t i_bytes, cbytes_t
u32 numMemories;
_ (ReadLEB_u32 (& numMemories, & i_bytes, i_end)); m3log (parse, "** Memory [%d]", numMemories);
if (numMemories == 1)
{
ParseType_Memory (& io_module->memoryInfo, & i_bytes, i_end);
}
else _throw (m3Err_tooManyMemorySections);
_throwif (m3Err_tooManyMemorySections, numMemories != 1);
ParseType_Memory (& io_module->memoryInfo, & i_bytes, i_end);
_catch: return result;
}
@ -427,8 +418,7 @@ _ (Module_AddGlobal (io_module, & global, type, isMutable, false /* isImpo
_ (Parse_InitExpr (io_module, & i_bytes, i_end));
global->initExprSize = (u32) (i_bytes - global->initExpr);
if (global->initExprSize <= 1)
_throw (m3Err_wasmMissingInitExpr);
_throwif (m3Err_wasmMissingInitExpr, global->initExprSize <= 1);
}
_catch: return result;
@ -537,51 +527,44 @@ M3Result m3_ParseModule (IM3Environment i_environment, IM3Module * o_module, c
IM3Module module;
_try {
_ (m3Alloc (& module, M3Module, 1));
// Module_Init (module);
module->name = ".unnamed"; m3log (parse, "load module: %d bytes", i_numBytes);
module->startFunction = -1;
module->hasWasmCodeCopy = false;
const u8 * pos = i_bytes;
const u8 * end = pos + i_numBytes;
u32 magic = 0;
u32 magic, version;
_ (Read_u32 (& magic, & pos, end));
if (magic == 0x6d736100)
_ (Read_u32 (& version, & pos, end));
_throwif (m3Err_wasmMalformed, magic != 0x6d736100);
_throwif (m3Err_incompatibleWasmVersion, version != 1);
m3log (parse, "found magic + version");
u8 previousSection = 0;
while (pos < end)
{
u32 version;
_ (Read_u32 (&version, & pos, end));
u8 section;
_ (ReadLEB_u7 (& section, & pos, end));
if (section > previousSection or // from the spec: sections must appear in order
section == 0 or // custom section
(section == 12 and section == 9) or // if present, DataCount goes after Element
(section == 10 and section == 12)) // and before Code
{
u32 sectionLength;
_ (ReadLEB_u32 (& sectionLength, & pos, end));
_ (ParseModuleSection (module, section, pos, sectionLength));
if (version == 1)
{ m3log (parse, "found magic + version");
u8 previousSection = 0;
pos += sectionLength;
while (pos < end)
{
u8 sectionCode;
_ (ReadLEB_u7 (& sectionCode, & pos, end));
if (sectionCode > previousSection or // from the spec: sections must appear in order
sectionCode == 0 or
(sectionCode == 12 and previousSection == 9) or // if present, DataCount goes after Element
(sectionCode == 10 and previousSection == 12) // and before Code
) {
u32 sectionLength;
_ (ReadLEB_u32 (& sectionLength, & pos, end));
_ (ParseModuleSection (module, sectionCode, pos, sectionLength));
pos += sectionLength;
if (sectionCode)
previousSection = sectionCode;
}
else _throw (m3Err_misorderedWasmSection);
}
if (section)
previousSection = section;
}
else _throw (m3Err_incompatibleWasmVersion);
else _throw (m3Err_misorderedWasmSection);
}
else _throw (m3Err_wasmMalformed);
} _catch:

@ -118,6 +118,9 @@ d_m3ErrorConst (tooManyMemorySections, "Wasm MVP can only define one me
d_m3ErrorConst (moduleAlreadyLinked, "attempting to bind module to multiple runtimes")
d_m3ErrorConst (functionLookupFailed, "function lookup failed")
d_m3ErrorConst (functionImportMissing, "missing imported function")
d_m3ErrorConst (malformedFunctionSignature, "malformed function signature")
d_m3ErrorConst (funcSignatureMissingReturnType,"function signature missing return type")
// compilation errors
d_m3ErrorConst (noCompiler, "no compiler found for opcode")

Loading…
Cancel
Save