diff --git a/source/extensions/m3_extensions.c b/source/extensions/m3_extensions.c new file mode 100644 index 0000000..7910c70 --- /dev/null +++ b/source/extensions/m3_extensions.c @@ -0,0 +1,27 @@ +// +// m3_extensions.c +// +// Created by Steven Massey on 3/30/21. +// Copyright © 2021 Steven Massey. All rights reserved. +// + +#include "wasm3_ext.h" +#include "m3_env.h" + + +IM3Module m3_NewModule (IM3Environment i_environment) +{ + IM3Module module = m3_AllocStruct (M3Module); + + if (module) + { + module->name = ".unnamed"; + module->startFunction = -1; + module->environment = i_environment; + + module->wasmStart = NULL; + module->wasmEnd = NULL; + } + + return module; +} diff --git a/source/extensions/wasm3_ext.h b/source/extensions/wasm3_ext.h new file mode 100644 index 0000000..5081389 --- /dev/null +++ b/source/extensions/wasm3_ext.h @@ -0,0 +1,31 @@ +// +// Wasm3, high performance WebAssembly interpreter +// +// Extensions +// +// Copyright © 2019-2021 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#ifndef wasm3_ext_h +#define wasm3_ext_h + +#include "wasm3.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +//------------------------------------------------------------------------------------------------------------------------------- +// modules +//------------------------------------------------------------------------------------------------------------------------------- + + // Creates an empty module. + IM3Module m3_NewModule (IM3Environment i_environment); + +#if defined(__cplusplus) +} +#endif + +#endif // wasm3_h diff --git a/source/m3_bind.c b/source/m3_bind.c index acd4e1c..c72b2be 100644 --- a/source/m3_bind.c +++ b/source/m3_bind.c @@ -30,6 +30,7 @@ M3Result SignatureToFuncType (IM3FuncType * o_functionType, ccstr_t i_signatur M3Result result = m3Err_none; IM3FuncType funcType = NULL; + _try { if (not o_functionType) _throw ("null function type"); @@ -43,7 +44,7 @@ _try { _throwif (m3Err_malformedFunctionSignature, maxNumArgs < 0); _throwif ("insane argument count", maxNumArgs > d_m3MaxSaneFunctionArgCount); - const unsigned umaxNumArgs = (unsigned)maxNumArgs; + const u32 umaxNumArgs = (u32) maxNumArgs; _ (AllocFuncType (& funcType, umaxNumArgs)); diff --git a/source/m3_env.c b/source/m3_env.c index 5fcc25b..9bfca5e 100644 --- a/source/m3_env.c +++ b/source/m3_env.c @@ -177,22 +177,38 @@ void FreeImportInfo (M3ImportInfo * i_info) IM3Environment m3_NewEnvironment () { + M3Result result = m3Err_none; + IM3Environment env = m3_AllocStruct (M3Environment); - if (!env) return NULL; - // create FuncTypes for all simple block return ValueTypes - for (int t = c_m3Type_none; t <= c_m3Type_f64; t++) - { - d_m3Assert (t < 5); - - IM3FuncType ftype; - AllocFuncType (& ftype, 1); - ftype->numArgs = 0; - ftype->numRets = (t == c_m3Type_none) ? 0 : 1; - ftype->types[0] = t; - - env->retFuncTypes[t] = ftype; - } + if (env) + { + _try + { + // create FuncTypes for all simple block return ValueTypes + for (int t = c_m3Type_none; t <= c_m3Type_f64; t++) + { + IM3FuncType ftype; +_ (AllocFuncType (& ftype, 1)); + + ftype->numArgs = 0; + ftype->numRets = (t == c_m3Type_none) ? 0 : 1; + ftype->types [0] = t; + + Environment_AddFuncType (env, & ftype); + + d_m3Assert (t < 5); + env->retFuncTypes [t] = ftype; + } + } + + _catch: + if (result) + { + m3_FreeEnvironment (env); + env = NULL; + } + } return env; } @@ -208,13 +224,7 @@ void Environment_Release (IM3Environment i_environment) m3_Free (ftype); ftype = next; } - for (int t = c_m3Type_none; t <= c_m3Type_f64; t++) - { - d_m3Assert (t < 5); - ftype = i_environment->retFuncTypes[t]; - d_m3Assert (ftype->next == NULL); - m3_Free (ftype); - } + m3log (runtime, "freeing %d pages from environment", CountCodePages (i_environment->pagesReleased)); FreeCodePages (& i_environment->pagesReleased); } @@ -230,6 +240,7 @@ void m3_FreeEnvironment (IM3Environment i_environment) } +// returns the same io_funcType or replaces it with an equivalent that's already in the type linked list void Environment_AddFuncType (IM3Environment i_environment, IM3FuncType * io_funcType) { IM3FuncType addType = * io_funcType; diff --git a/source/m3_env.h b/source/m3_env.h index 1155e05..fc9d388 100644 --- a/source/m3_env.h +++ b/source/m3_env.h @@ -193,9 +193,9 @@ typedef struct M3Environment { // struct M3Runtime * runtimes; - IM3FuncType funcTypes; // linked list + IM3FuncType funcTypes; // linked list - IM3FuncType retFuncTypes[5]; // the number of elements must match the basic types as per M3ValueType + IM3FuncType retFuncTypes [c_m3Type_unknown]; // the number of elements must match the basic types as per M3ValueType M3CodePage * pagesReleased; } diff --git a/source/wasm3.h b/source/wasm3.h index c6face8..7bcb45f 100644 --- a/source/wasm3.h +++ b/source/wasm3.h @@ -178,31 +178,31 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") void m3_FreeRuntime (IM3Runtime i_runtime); + // Wasm currently only supports one memory region. i_memoryIndex should be zero. uint8_t * m3_GetMemory (IM3Runtime i_runtime, uint32_t * o_memorySizeInBytes, uint32_t i_memoryIndex); void * m3_GetUserData (IM3Runtime i_runtime); - // Wasm currently only supports one memory region. i_memoryIndex should be zero. //------------------------------------------------------------------------------------------------------------------------------- // modules //------------------------------------------------------------------------------------------------------------------------------- + // i_wasmBytes data must be persistent during the lifetime of the module M3Result m3_ParseModule (IM3Environment i_environment, IM3Module * o_module, const uint8_t * const i_wasmBytes, uint32_t i_numWasmBytes); - // i_wasmBytes data must be persistent during the lifetime of the module - + + // Only unloaded modules need to be freed void m3_FreeModule (IM3Module i_module); - // Only unloaded modules need to be freed + // LoadModule transfers ownership of a module to the runtime. Do not free modules once successfully imported into the runtime M3Result m3_LoadModule (IM3Runtime io_runtime, IM3Module io_module); - // LoadModule transfers ownership of a module to the runtime. Do not free modules once successfully imported into the runtime - // Calling m3_RunStart is optional + // Calling m3_RunStart is optional M3Result m3_RunStart (IM3Module i_module); typedef const void * (* M3RawCall) (IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem); @@ -228,6 +228,7 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") //------------------------------------------------------------------------------------------------------------------------------- M3Result m3_Yield (void); + // o_function is valid during the lifetime of the originating runtime M3Result m3_FindFunction (IM3Function * o_function, IM3Runtime i_runtime, const char * const i_functionName); @@ -246,7 +247,6 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") M3Result m3_GetResultsVL (IM3Function i_function, va_list o_rets); M3Result m3_GetResults (IM3Function i_function, uint32_t i_retc, const void * o_retptrs[]); - // IM3Functions are valid during the lifetime of the originating runtime void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* o_info); void m3_ResetErrorInfo (IM3Runtime i_runtime); @@ -262,7 +262,7 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") void m3_PrintM3Info (void); void m3_PrintProfilerInfo (void); - // The runtime owns the backtrace, do not free the backtrace you obtain. Returns NULL if there's no backtrace. + // The runtime owns the backtrace, do not free the backtrace you obtain. Returns NULL if there's no backtrace. IM3BacktraceInfo m3_GetBacktrace (IM3Runtime i_runtime); #if defined(__cplusplus) diff --git a/test/internal/m3_test.c b/test/internal/m3_test.c index 673e11f..edccac0 100644 --- a/test/internal/m3_test.c +++ b/test/internal/m3_test.c @@ -7,7 +7,7 @@ #include -//#include "m3_ext.h" +#include "wasm3_ext.h" #include "m3_bind.h" #define Test(NAME) printf ("\n test: %s\n", #NAME); @@ -22,15 +22,16 @@ int main (int i_argc, const char * i_argv []) IM3FuncType ftype = NULL; result = SignatureToFuncType (& ftype, ""); expect (result == m3Err_malformedFunctionSignature) - m3Free (ftype); + m3_Free (ftype); - result = SignatureToFuncType (& ftype, "()"); expect (result == m3Err_malformedFunctionSignature) - m3Free (ftype); + // implicit void return + result = SignatureToFuncType (& ftype, "()"); expect (result == m3Err_none) + m3_Free (ftype); result = SignatureToFuncType (& ftype, " v () "); expect (result == m3Err_none) expect (ftype->numRets == 0) expect (ftype->numArgs == 0) - m3Free (ftype); + m3_Free (ftype); result = SignatureToFuncType (& ftype, "f(IiF)"); expect (result == m3Err_none) expect (ftype->numRets == 1) @@ -43,8 +44,8 @@ int main (int i_argc, const char * i_argv []) IM3FuncType ftype2 = NULL; result = SignatureToFuncType (& ftype2, "f(I i F)"); expect (result == m3Err_none); expect (AreFuncTypesEqual (ftype, ftype2)); - m3Free (ftype); - m3Free (ftype2); + m3_Free (ftype); + m3_Free (ftype2); } @@ -72,6 +73,7 @@ int main (int i_argc, const char * i_argv []) Environment_Release (& env); expect (CountCodePages (env.pagesReleased) == 0); } + Test (codepages.b) { const u32 c_numPages = 2000; @@ -103,7 +105,7 @@ int main (int i_argc, const char * i_argv []) expect (runtime.numActiveCodePages == numActive); } - + printf ("num pages: %d\n", runtime.numCodePages); for (u32 i = 0; i < c_numPages; ++i) @@ -119,6 +121,21 @@ int main (int i_argc, const char * i_argv []) Runtime_Release (& runtime); Environment_Release (& env); } + + + Test (extensions) + { + IM3Environment env = m3_NewEnvironment (); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + + IM3Module module = m3_NewModule (env); + + M3Result result = m3_LoadModule (runtime, module); expect (result == m3Err_none) + + m3_FreeRuntime (runtime); + } + return 0; }