diff --git a/platforms/app/main.c b/platforms/app/main.c index 7f9f264..172ede8 100644 --- a/platforms/app/main.c +++ b/platforms/app/main.c @@ -92,10 +92,19 @@ M3Result link_all (IM3Module module) return res; } +const char* modname_from_fn(const char* fn) +{ + const char* off = strrchr(fn, '/'); + if (off) return off+1; + off = strrchr(fn, '\\'); + if (off) return off+1; + return fn; +} M3Result repl_load (const char* fn) { M3Result result = m3Err_none; + IM3Module module = NULL; u8* wasm = NULL; u32 fsize = 0; @@ -129,13 +138,14 @@ M3Result repl_load (const char* fn) fclose (f); f = NULL; - IM3Module module; result = m3_ParseModule (env, &module, wasm, fsize); if (result) goto on_error; result = m3_LoadModule (runtime, module); if (result) goto on_error; + m3_SetModuleName(module, modname_from_fn(fn)); + result = link_all (module); if (result) goto on_error; @@ -144,7 +154,9 @@ M3Result repl_load (const char* fn) } return result; + on_error: + m3_FreeModule(module); if (wasm) free(wasm); if (f) fclose(f); diff --git a/source/m3_api_defs.h b/source/m3_api_defs.h index 9d52bac..221d962 100644 --- a/source/m3_api_defs.h +++ b/source/m3_api_defs.h @@ -32,16 +32,20 @@ #define m3ApiSuccess() { return m3Err_none; } # if defined(M3_BIG_ENDIAN) +# define m3ApiReadMem8(ptr) (* (u8 *)(ptr)) # define m3ApiReadMem16(ptr) __builtin_bswap16((* (u16 *)(ptr))) # define m3ApiReadMem32(ptr) __builtin_bswap32((* (u32 *)(ptr))) # define m3ApiReadMem64(ptr) __builtin_bswap64((* (u64 *)(ptr))) +# define m3ApiWriteMem8(ptr, val) { * (u8 *)(ptr) = (val); } # define m3ApiWriteMem16(ptr, val) { * (u16 *)(ptr) = __builtin_bswap16((val)); } # define m3ApiWriteMem32(ptr, val) { * (u32 *)(ptr) = __builtin_bswap32((val)); } # define m3ApiWriteMem64(ptr, val) { * (u64 *)(ptr) = __builtin_bswap64((val)); } # else +# define m3ApiReadMem8(ptr) (* (u8 *)(ptr)) # define m3ApiReadMem16(ptr) (* (u16 *)(ptr)) # define m3ApiReadMem32(ptr) (* (u32 *)(ptr)) # define m3ApiReadMem64(ptr) (* (u64 *)(ptr)) +# define m3ApiWriteMem8(ptr, val) { * (u8 *)(ptr) = (val); } # define m3ApiWriteMem16(ptr, val) { * (u16 *)(ptr) = (val); } # define m3ApiWriteMem32(ptr, val) { * (u32 *)(ptr) = (val); } # define m3ApiWriteMem64(ptr, val) { * (u64 *)(ptr) = (val); } diff --git a/source/m3_compile.c b/source/m3_compile.c index 2f7f9e7..6912fb7 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -362,7 +362,7 @@ u16 GetMaxUsedSlotPlusOne (IM3Compilation o) o->slotMaxAllocatedIndexPlusOne--; } - + # ifdef DEBUG u16 maxSlot = o->slotMaxAllocatedIndexPlusOne; while (maxSlot < d_m3MaxFunctionSlots) @@ -465,8 +465,8 @@ M3Result Push (IM3Compilation o, u8 i_type, u16 i_slot) u32 regSelect = IsFpRegisterSlotAlias (i_slot); AllocateRegister (o, regSelect, stackIndex); } - - if (d_m3LogWasmStack) dump_type_stack (o); + + if (d_m3LogWasmStack) dump_type_stack (o); } else result = m3Err_functionStackOverflow; @@ -1062,7 +1062,8 @@ _ (CopyStackIndexToSlot (o, returnSlot, stackTop--)); _ (Pop (o)); } } - _catch: return result; + + _catch: return result; } @@ -1482,7 +1483,7 @@ _ (GetBlockScope (o, & scope, target)); // create a ContinueLoop operation on a fresh page _ (AcquireCompilationCodePage (o, & continueOpPage)); - + pc_t startPC = GetPagePC (continueOpPage); IM3CodePage savedPage = o->page; o->page = continueOpPage; @@ -1514,7 +1515,7 @@ _ (EmitPatchingBranch (o, scope)); } } } - + ReleaseCompilationCodePage (o); // FIX: continueOpPage can get lost if thrown o->page = savedPage; @@ -2367,7 +2368,7 @@ const M3OpInfo c_operations [] = d_m3DebugOp (CopySlot_32), d_m3DebugOp (PreserveCopySlot_32), d_m3DebugOp (If_s), d_m3DebugOp (BranchIfPrologue_s), d_m3DebugOp (CopySlot_64), d_m3DebugOp (PreserveCopySlot_64), d_m3DebugOp (If_r), d_m3DebugOp (BranchIfPrologue_r), - + d_m3DebugOp (Select_i32_rss), d_m3DebugOp (Select_i32_srs), d_m3DebugOp (Select_i32_ssr), d_m3DebugOp (Select_i32_sss), d_m3DebugOp (Select_i64_rss), d_m3DebugOp (Select_i64_srs), d_m3DebugOp (Select_i64_ssr), d_m3DebugOp (Select_i64_sss), @@ -2744,7 +2745,7 @@ _ (CompileLocals (o)); _ (ReserveConstants (o)); // start tracking the max stack used (Push() also updates this value) so that op_Entry can precisely detect stack overflow - o->function->maxStackSlots = o->slotMaxAllocatedIndexPlusOne = o->slotFirstDynamicIndex; + o->maxStackSlots = o->slotMaxAllocatedIndexPlusOne = o->slotFirstDynamicIndex; o->block.blockStackIndex = o->stackFirstDynamicIndex = o->stackIndex; m3log (compile, "start stack index: %d", (u32) o->stackFirstDynamicIndex); @@ -2757,6 +2758,7 @@ _ (CompileBlockStatements (o)); _throwif(m3Err_wasmMalformed, o->previousOpcode != c_waOp_end); io_function->compiled = pc; + io_function->maxStackSlots = o->maxStackSlots; u16 numConstantSlots = o->slotMaxConstIndex - o->slotFirstConstIndex; m3log (compile, "unique constant slots: %d; unused slots: %d", numConstantSlots, o->slotFirstDynamicIndex - o->slotMaxConstIndex); diff --git a/source/m3_compile.h b/source/m3_compile.h index c97cda4..cca423f 100644 --- a/source/m3_compile.h +++ b/source/m3_compile.h @@ -91,6 +91,8 @@ typedef struct u16 slotFirstLocalIndex; u16 slotFirstDynamicIndex; // numArgs + numLocals + numReservedConstants. the first mutable slot available to the compiler. + u16 maxStackSlots; + m3slot_t constants [d_m3MaxConstantTableSize]; // 'wasmStack' holds slot locations diff --git a/source/m3_core.c b/source/m3_core.c index b1e3cea..0d9ffed 100644 --- a/source/m3_core.c +++ b/source/m3_core.c @@ -117,7 +117,7 @@ void * m3_Malloc (size_t i_size) void m3_FreeImpl (void * io_ptr) { // if (io_ptr) printf("== free %p\n", io_ptr); - free ((void*)io_ptr); + free (io_ptr); } void * m3_Realloc (void * i_ptr, size_t i_newSize, size_t i_oldSize) diff --git a/source/m3_env.c b/source/m3_env.c index d707265..ea1d565 100644 --- a/source/m3_env.c +++ b/source/m3_env.c @@ -286,6 +286,10 @@ M3Result EvaluateExpression (IM3Module i_module, void * o_expressed, u8 i_type pc_t m3code = GetPagePC (o->page); result = CompileBlock (o, ftype, c_waOp_block); + if (not result && o->maxStackSlots >= runtime.numStackSlots) { + result = m3Err_trapStackOverflow; + } + if (not result) { m3ret_t r = Call (m3code, stack, NULL, d_m3OpDefaultArgs); @@ -542,28 +546,32 @@ M3Result m3_LoadModule (IM3Runtime io_runtime, IM3Module io_module) { M3Result result = m3Err_none; - if (not io_module->runtime) - { - io_module->runtime = io_runtime; - M3Memory * memory = & io_runtime->memory; + if (UNLIKELY(io_module->runtime)) { + return m3Err_moduleAlreadyLinked; + } -_ (InitMemory (io_runtime, io_module)); -_ (InitGlobals (io_module)); -_ (InitDataSegments (memory, io_module)); -_ (InitElements (io_module)); + io_module->runtime = io_runtime; + M3Memory * memory = & io_runtime->memory; - io_module->next = io_runtime->modules; - io_runtime->modules = io_module; +_ (InitMemory (io_runtime, io_module)); +_ (InitGlobals (io_module)); +_ (InitDataSegments (memory, io_module)); +_ (InitElements (io_module)); - // Start func might use imported functions, which are not liked here yet, - // so it will be called before a function call is attempted (in m3_FindFuSnction) - } - else result = m3Err_moduleAlreadyLinked; + // Start func might use imported functions, which are not liked here yet, + // so it will be called before a function call is attempted (in m3_FindFunction) - if (result) - io_module->runtime = NULL; +#ifdef DEBUG + Module_GenerateNames(io_module); +#endif - _catch: return result; + io_module->next = io_runtime->modules; + io_runtime->modules = io_module; + return result; // ok + +_catch: + io_module->runtime = NULL; + return result; } IM3Global m3_FindGlobal (IM3Module io_module, diff --git a/source/m3_env.h b/source/m3_env.h index 5f5c482..33d0e00 100644 --- a/source/m3_env.h +++ b/source/m3_env.h @@ -123,6 +123,8 @@ M3Result Module_AddGlobal (IM3Module io_module, IM M3Result Module_AddFunction (IM3Module io_module, u32 i_typeIndex, IM3ImportInfo i_importInfo /* can be null */); IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex); +void Module_GenerateNames (IM3Module i_module); + void FreeImportInfo (M3ImportInfo * i_info); //--------------------------------------------------------------------------------------------------------------------------------- diff --git a/source/m3_exec.h b/source/m3_exec.h index 2df684b..54b5a91 100644 --- a/source/m3_exec.h +++ b/source/m3_exec.h @@ -744,13 +744,7 @@ d_m3Op (Entry) } #if d_m3EnableStrace >= 2 - u16 numNames = 0; - cstr_t *names = GetFunctionNames(function, &numNames); - if (numNames) { - d_m3TracePrint("%s %s {", names[0], SPrintFunctionArgList (function, _sp)); - } else { - d_m3TracePrint("$%d %s {", function->index, SPrintFunctionArgList (function, _sp)); - } + d_m3TracePrint("%s %s {", m3_GetFunctionName(function), SPrintFunctionArgList (function, _sp)); trace_rt->callDepth++; #endif diff --git a/source/m3_function.h b/source/m3_function.h index d038af9..7173b8b 100644 --- a/source/m3_function.h +++ b/source/m3_function.h @@ -63,7 +63,7 @@ typedef struct M3Function u32 hits; #endif -# if d_m3EnableStrace >= 2 || d_m3LogCompile +# if d_m3LogCompile u32 index; # endif diff --git a/source/m3_info.c b/source/m3_info.c index 4174172..4805c83 100644 --- a/source/m3_info.c +++ b/source/m3_info.c @@ -250,24 +250,20 @@ d_m3Decoder (BranchTable) { u32 slot = fetch (u32); - sprintf (o_string, "slot: %" PRIu32 "; targets: ", slot); + o_string += sprintf (o_string, "slot: %" PRIu32 "; targets: ", slot); // IM3Function function = fetch2 (IM3Function); i32 targets = fetch (i32); - char str [1000]; - for (i32 i = 0; i < targets; ++i) { pc_t addr = fetch (pc_t); - sprintf (str, "%" PRIi32 "=%p, ", i, addr); - strcat (o_string, str); + o_string += sprintf (o_string, "%" PRIi32 "=%p, ", i, addr); } pc_t addr = fetch (pc_t); - sprintf (str, "def=%p ", addr); - strcat (o_string, str); + sprintf (o_string, "def=%p ", addr); } @@ -315,7 +311,7 @@ void dump_code_page (IM3CodePage i_codePage, pc_t i_startPC) if (i.info) { - char infoString [1000] = { 0 }; + char infoString [8*1024] = { 0 }; DecodeOperation (infoString, i.opcode, op, i.info, & pc); @@ -424,7 +420,7 @@ void dump_type_stack (IM3Compilation o) // d_m3Assert (regAllocated [r] == 0); // reg allocation & stack out of sync u16 maxSlot = GetMaxUsedSlotPlusOne (o); - + if (maxSlot > o->slotFirstDynamicIndex) { d_m3Log (stack, " -"); @@ -445,7 +441,7 @@ void dump_type_stack (IM3Compilation o) { printf ("%3d|", o->m3Slots [i]); } - + printf ("\n"); } d_m3Log(stack, "\n"); diff --git a/source/m3_module.c b/source/m3_module.c index 1566fb0..0286409 100644 --- a/source/m3_module.c +++ b/source/m3_module.c @@ -37,9 +37,6 @@ void m3_FreeModule (IM3Module i_module) for (u32 i = 0; i < i_module->numGlobals; ++i) { m3_Free (i_module->globals[i].name); - } - for (u32 i = 0; i < i_module->numGlobals; ++i) - { FreeImportInfo(&(i_module->globals[i].import)); } m3_Free (i_module->globals); @@ -84,15 +81,15 @@ _try { IM3Function func = Module_GetFunction (io_module, index); func->funcType = ft; -#if d_m3EnableStrace >= 2 || d_m3LogCompile +# if d_m3LogCompile func->index = index; -#endif +# endif if (i_importInfo and func->numNames == 0) { func->import = * i_importInfo; - func->numNames = 1; func->names[0] = i_importInfo->fieldUtf8; + func->numNames = 1; } m3log (module, " added function: %3d; sig: %d", index, i_typeIndex); @@ -101,6 +98,32 @@ _try { return result; } +void Module_GenerateNames (IM3Module i_module) +{ + for (u32 i = 0; i < i_module->numFunctions; ++i) + { + IM3Function func = & i_module->functions [i]; + + if (func->numNames == 0) + { + char* buff = m3_AllocArray(char, 16); + snprintf(buff, 16, "$func%d", i); + func->names[0] = buff; + func->numNames = 1; + } + } + for (u32 i = 0; i < i_module->numGlobals; ++i) + { + IM3Global global = & i_module->globals [i]; + + if (global->name == NULL) + { + char* buff = m3_AllocArray(char, 16); + snprintf(buff, 16, "$global%d", i); + global->name = buff; + } + } +} IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex) { @@ -119,11 +142,16 @@ IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex) const char* m3_GetModuleName (IM3Module i_module) { if (!i_module || !i_module->name) - return ""; + return ".unnamed"; return i_module->name; } +void m3_SetModuleName (IM3Module i_module, const char* name) +{ + if (i_module) i_module->name = name; +} + IM3Runtime m3_GetModuleRuntime (IM3Module i_module) { return i_module ? i_module->runtime : NULL; diff --git a/source/m3_parse.c b/source/m3_parse.c index 81f55f5..4ea7bb1 100644 --- a/source/m3_parse.c +++ b/source/m3_parse.c @@ -127,6 +127,8 @@ _ (ReadLEB_u32 (& numFunctions, & i_bytes, i_end)); _throwif("too many functions", numFunctions > d_m3MaxSaneFunctionsCount); + // TODO: prealloc functions + for (u32 i = 0; i < numFunctions; ++i) { u32 funcTypeIndex; @@ -236,18 +238,19 @@ _ (ReadLEB_u32 (& index, & i_bytes, i_end)); if (exportKind == d_externalKind_function) { _throwif(m3Err_wasmMalformed, index >= io_module->numFunctions); - u16 numNames = io_module->functions [index].numNames; - if (numNames < d_m3MaxDuplicateFunctionImpl) + IM3Function func = &(io_module->functions [index]); + if (func->numNames < d_m3MaxDuplicateFunctionImpl) { - io_module->functions [index].numNames++; - io_module->functions [index].names[numNames] = utf8; + func->names[func->numNames++] = utf8; utf8 = NULL; // ownership transferred to M3Function } } else if (exportKind == d_externalKind_global) { _throwif(m3Err_wasmMalformed, index >= io_module->numGlobals); - io_module->globals[index].name = utf8; + IM3Global global = &(io_module->globals [index]); + m3_Free (global->name); + global->name = utf8; utf8 = NULL; // ownership transferred to M3Global } @@ -506,10 +509,11 @@ _ (Read_utf8 (& name, & i_bytes, i_end)); if (index < io_module->numFunctions) { - if (io_module->functions [index].numNames == 0) + IM3Function func = &(io_module->functions [index]); + if (func->numNames == 0) { - io_module->functions [index].numNames = 1; - io_module->functions [index].names[0] = name; m3log (parse, " naming function%5d: %s", index, name); + func->names[0] = name; m3log (parse, " naming function%5d: %s", index, name); + func->numNames = 1; name = NULL; // transfer ownership } // else m3log (parse, "prenamed: %s", io_module->functions [index].name); diff --git a/source/wasm3.h b/source/wasm3.h index caf7cbd..32fb3e1 100644 --- a/source/wasm3.h +++ b/source/wasm3.h @@ -246,6 +246,7 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") const void * i_userdata); const char* m3_GetModuleName (IM3Module i_module); + void m3_SetModuleName (IM3Module i_module, const char* name); IM3Runtime m3_GetModuleRuntime (IM3Module i_module); //------------------------------------------------------------------------------------------------------------------------------- diff --git a/test/run-wasi-test.py b/test/run-wasi-test.py index 02cdfcf..f789e79 100755 --- a/test/run-wasi-test.py +++ b/test/run-wasi-test.py @@ -65,7 +65,7 @@ commands_full = [ "args": ["16", "64"], "expect_sha1": "d85df3561eb15f6f0e6f20d5640e8e1306222c6d" }, { - "skip": True, # Fails on Windows-uvwasi, on CI only (CNR locally) + "skip": True, # TODO "name": "mal", "wasm": "./wasi/mal/mal.wasm", "args": ["./wasi/mal/test-fib.mal", "16"], @@ -127,6 +127,7 @@ commands_fast = [ "args": ["4", "32"], "expect_sha1": "ea05d85998b2f453b588ef76a1256215bf9b851c" }, { + "skip": True, # TODO "name": "mal", "wasm": "./wasi/mal/mal.wasm", "args": ["./wasi/mal/test-fib.mal", "16"], @@ -176,9 +177,9 @@ for cmd in commands: stats.timeout += 1 fail("Timeout") continue - except subprocess.CalledProcessError: + except subprocess.CalledProcessError as e: stats.crashed += 1 - fail("Crashed") + fail(f"Exited with error code {e.returncode}") continue if "expect_sha1" in cmd: