diff --git a/source/extensions/m3_extensions.c b/source/extensions/m3_extensions.c index 14fcc47..8adeb67 100644 --- a/source/extensions/m3_extensions.c +++ b/source/extensions/m3_extensions.c @@ -15,7 +15,7 @@ IM3Module m3_NewModule (IM3Environment i_environment) { IM3Module module = m3_AllocStruct (M3Module); - + if (module) { module->name = ".unnamed"; @@ -25,7 +25,7 @@ IM3Module m3_NewModule (IM3Environment i_environment) module->wasmStart = NULL; module->wasmEnd = NULL; } - + return module; } @@ -47,7 +47,7 @@ _ (SignatureToFuncType (& ftype, i_signature)); bytes_t bytes = i_wasmBytes; bytes_t end = i_wasmBytes + 5; - + u32 size; _ (ReadLEB_u32 (& size, & bytes, end)); end = bytes + size; @@ -55,7 +55,7 @@ _ (ReadLEB_u32 (& size, & bytes, end)); if (index >= 0) { _throwif ("function index out of bounds", index >= i_module->numFunctions); - + function = & i_module->functions [index]; if (not AreFuncTypesEqual (ftype, function->funcType)) @@ -72,11 +72,11 @@ _ (ReadLEB_u32 (& size, & bytes, end)); Environment_AddFuncType (i_module->environment, & ftype); i_module->funcTypes [funcTypeIndex] = ftype; ftype = NULL; // prevent freeing below - + index = (i32) i_module->numFunctions; _ (Module_AddFunction (i_module, funcTypeIndex, NULL)); function = Module_GetFunction (i_module, index); - + * io_functionIndex = index; } @@ -84,22 +84,22 @@ _ (Module_AddFunction (i_module, funcTypeIndex, NULL)); if (function->ownsWasmCode) m3_Free (function->wasm); - + size_t numBytes = end - i_wasmBytes; function->wasm = m3_CopyMem (i_wasmBytes, numBytes); _throwifnull (function->wasm); function->wasmEnd = function->wasm + numBytes; function->ownsWasmCode = true; - + if (i_doCompilation and not i_module->runtime) _throw ("module must be loaded into runtime to compile function"); - + _ (Compile_Function (function)); - + _catch: m3_Free (ftype); - + return result; } diff --git a/source/m3_bind.c b/source/m3_bind.c index 0ec1d03..8383cf0 100644 --- a/source/m3_bind.c +++ b/source/m3_bind.c @@ -30,7 +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"); diff --git a/source/m3_compile.c b/source/m3_compile.c index 184ab50..94d66ee 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -499,15 +499,15 @@ M3Result Pop (IM3Compilation o) M3Result PopType (IM3Compilation o, u8 i_type) { M3Result result = m3Err_none; - + u8 topType = GetStackTopType (o); - + if (i_type == topType or o->block.isPolymorphic) { result = Pop (o); } else result = m3Err_typeMismatch; - + return result; } @@ -1011,7 +1011,7 @@ M3Result Compile_Return (IM3Compilation o, m3opcode_t i_opcode) if (GetFunctionNumReturns (o->function)) { u8 type = GetFunctionReturnType (o->function, 0); - + _ (ReturnStackTop (o)); _ (PopType (o, type)); } @@ -1037,7 +1037,7 @@ M3Result Compile_End (IM3Compilation o, m3opcode_t i_opcode) { if (not o->block.isPolymorphic and type != GetStackTopType (o)) _throw (m3Err_typeMismatch); - + // if there are branches to the function end, then their values are in a register // if the block happens to have its top in a register too, then we can patch the branch // to here. Otherwise, an ReturnStackTop is appended to the end of the function (at B) and @@ -1486,13 +1486,15 @@ _ (EmitOp (o, op_CallIndirect)); } -M3Result Compile_Memory_Current (IM3Compilation o, m3opcode_t i_opcode) +M3Result Compile_Memory_Size (IM3Compilation o, m3opcode_t i_opcode) { M3Result result; i8 reserved; _ (ReadLEB_i7 (& reserved, & o->wasm, o->wasmEnd)); +_ (PreserveRegisterIfOccupied (o, c_m3Type_i32)); + _ (EmitOp (o, op_MemCurrent)); _ (PushRegister (o, c_m3Type_i32)); @@ -1971,8 +1973,8 @@ const M3OpInfo c_operations [] = M3OP( "i64.store16", -2, none, d_binOpList (i64, Store_i16), Compile_Load_Store ), // 0x3d M3OP( "i64.store32", -2, none, d_binOpList (i64, Store_i32), Compile_Load_Store ), // 0x3e - M3OP( "memory.current", 1, i_32, d_logOp (MemCurrent), Compile_Memory_Current ), // 0x3f - M3OP( "memory.grow", 1, i_32, d_logOp (MemGrow), Compile_Memory_Grow ), // 0x40 + M3OP( "memory.size", 1, i_32, d_logOp (MemCurrent), Compile_Memory_Size ), // 0x3f + M3OP( "memory.grow", 1, i_32, d_logOp (MemGrow), Compile_Memory_Grow ), // 0x40 M3OP( "i32.const", 1, i_32, d_logOp (Const32), Compile_Const_i32 ), // 0x41 M3OP( "i64.const", 1, i_64, d_logOp (Const64), Compile_Const_i64 ), // 0x42 @@ -2190,14 +2192,9 @@ M3Result Compile_BlockStatements (IM3Compilation o) while (o->wasm < o->wasmEnd) { emit_stack_dump (o); + m3opcode_t opcode; o->lastOpcodeStart = o->wasm; - m3opcode_t opcode = * (o->wasm++); log_opcode (o, opcode); - -#ifndef d_m3CompileExtendedOpcode - if (UNLIKELY(opcode == 0xFC)) { - opcode = (opcode << 8) | (* (o->wasm++)); - } -#endif +_ (Read_opcode (& opcode, & o->wasm, o->wasmEnd)); log_opcode (o, opcode); IM3OpInfo opinfo = GetOpInfo(opcode); _throwif (m3Err_unknownOpcode, opinfo == NULL); @@ -2380,7 +2377,7 @@ _try { // skip over code size. the end was already calculated during parse phase u32 size; _ (ReadLEB_u32 (& size, & o->wasm, o->wasmEnd)); d_m3Assert (size == (o->wasmEnd - o->wasm)) - + _ (AcquireCompilationCodePage (o, & o->page)); pc_t pc = GetPagePC (o->page); diff --git a/source/m3_core.c b/source/m3_core.c index faaf845..b1e3cea 100644 --- a/source/m3_core.c +++ b/source/m3_core.c @@ -305,7 +305,32 @@ M3Result Read_u8 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end) if (ptr < i_end) { * o_value = * ptr; - ptr += sizeof (u8); + * io_bytes = ptr + 1; + + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + +M3Result Read_opcode (m3opcode_t * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + + if (ptr < i_end) + { + m3opcode_t opcode = * ptr++; + +#ifndef d_m3CompileExtendedOpcode + if (UNLIKELY(opcode == 0xFC)) + { + if (ptr < i_end) + { + opcode = (opcode << 8) | (* ptr++); + } + else return m3Err_wasmUnderrun; + } +#endif + * o_value = opcode; * io_bytes = ptr; return m3Err_none; diff --git a/source/m3_core.h b/source/m3_core.h index 0f2d9d7..fb4cfe1 100644 --- a/source/m3_core.h +++ b/source/m3_core.h @@ -84,12 +84,6 @@ const void * const cvptr_t; # define m3log_compile(...) {} # endif -# if d_m3LogWasmStack -# define m3log_stack(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) -# else -# define m3log_stack(...) {} -# endif - # if d_m3LogEmit # define m3log_emit(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) # else @@ -121,7 +115,7 @@ const void * const cvptr_t; # endif -# if (defined(DEBUG) && !defined(NASSERTS)) +# if defined(ASSERTS) || (defined(DEBUG) && !defined(NASSERTS)) # define d_m3Assert(ASS) if (!(ASS)) { printf("Assertion failed at %s:%d : %s\n", __FILE__, __LINE__, #ASS); abort(); } # else # define d_m3Assert(ASS) @@ -228,6 +222,7 @@ M3Result Read_f64 (f64 * o_value, bytes_t * io_bytes, cbytes_t M3Result Read_f32 (f32 * o_value, bytes_t * io_bytes, cbytes_t i_end); #endif M3Result Read_u8 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result Read_opcode (m3opcode_t * o_value, bytes_t * io_bytes, cbytes_t i_end); M3Result ReadLebUnsigned (u64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end); M3Result ReadLebSigned (i64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end); diff --git a/source/m3_env.c b/source/m3_env.c index bb70ab3..d31eec8 100644 --- a/source/m3_env.c +++ b/source/m3_env.c @@ -163,12 +163,12 @@ u32 GetFunctionNumReturns (IM3Function i_function) u8 GetFunctionReturnType (IM3Function i_function, u32 i_index) { u8 type = c_m3Type_none; - + if (i_index < GetFunctionNumReturns (i_function)) { type = i_function->funcType->types [i_index]; } - + return type; } @@ -192,7 +192,7 @@ void FreeImportInfo (M3ImportInfo * i_info) IM3Environment m3_NewEnvironment () { M3Result result = m3Err_none; - + IM3Environment env = m3_AllocStruct (M3Environment); if (env) @@ -215,7 +215,7 @@ _ (AllocFuncType (& ftype, 1)); env->retFuncTypes [t] = ftype; } } - + _catch: if (result) { @@ -238,7 +238,7 @@ void Environment_Release (IM3Environment i_environment) m3_Free (ftype); ftype = next; } - + m3log (runtime, "freeing %d pages from environment", CountCodePages (i_environment->pagesReleased)); FreeCodePages (& i_environment->pagesReleased); } diff --git a/source/m3_info.c b/source/m3_info.c index 8d7464a..6e909a3 100644 --- a/source/m3_info.c +++ b/source/m3_info.c @@ -275,8 +275,6 @@ void DecodeOperation (char * o_string, u8 i_opcode, IM3Operation i_operation, } } - -# ifdef DEBUG // WARNING/TODO: this isn't fully implemented. it blindly assumes each word is a Operation pointer // and, if an operation happens to missing from the c_operations table it won't be recognized here void dump_code_page (IM3CodePage i_codePage, pc_t i_startPC) @@ -312,7 +310,6 @@ void dump_code_page (IM3CodePage i_codePage, pc_t i_startPC) m3log (code, "free-lines: %d", i_codePage->info.numLines - i_codePage->info.lineIndex); } -# endif void dump_type_stack (IM3Compilation o) @@ -400,17 +397,13 @@ const char * get_indention_string (IM3Compilation o) } -void log_opcode (IM3Compilation o, u8 i_opcode) +void log_opcode (IM3Compilation o, m3opcode_t i_opcode) { i32 depth = o->block.depth; if (i_opcode == c_waOp_end or i_opcode == c_waOp_else) depth--; -# ifdef DEBUG - m3log (compile, "%4d | 0x%02x %s %s", o->numOpcodes++, i_opcode, GetOpcodeIndentionString (depth), c_operations [i_opcode].name); -# else - m3log (compile, "%4d | 0x%02x %s", o->numOpcodes++, i_opcode, GetOpcodeIndentionString (depth)); -# endif + m3log (compile, "%4d | 0x%02x %s %s", o->numOpcodes++, i_opcode, GetOpcodeIndentionString (depth), GetOpInfo(i_opcode)->name); } @@ -432,7 +425,6 @@ void emit_stack_dump (IM3Compilation o) void log_emit (IM3Compilation o, IM3Operation i_operation) { -# ifdef DEBUG OpInfo i = find_operation_info (i_operation); d_m3Log(emit, ""); @@ -441,7 +433,6 @@ void log_emit (IM3Compilation o, IM3Operation i_operation) printf ("%p: %s\n", GetPC (o), i.info->name); } else printf ("not found: %p\n", i_operation); -# endif } #endif // DEBUG diff --git a/source/m3_info.h b/source/m3_info.h index 573f156..19f36cc 100644 --- a/source/m3_info.h +++ b/source/m3_info.h @@ -15,7 +15,7 @@ d_m3BeginExternC #ifdef DEBUG void dump_type_stack (IM3Compilation o); -void log_opcode (IM3Compilation o, u8 i_opcode); +void log_opcode (IM3Compilation o, m3opcode_t i_opcode); const char * get_indention_string (IM3Compilation o); void emit_stack_dump (IM3Compilation o); void log_emit (IM3Compilation o, IM3Operation i_operation); diff --git a/source/m3_module.c b/source/m3_module.c index ef0cbd1..450d947 100644 --- a/source/m3_module.c +++ b/source/m3_module.c @@ -66,7 +66,7 @@ _try { M3Result Module_AddFunction (IM3Module io_module, u32 i_typeIndex, IM3ImportInfo i_importInfo) { M3Result result = m3Err_none; - + _try { u32 index = io_module->numFunctions++; io_module->functions = m3_ReallocArray (M3Function, io_module->functions, io_module->numFunctions, index); @@ -87,7 +87,7 @@ _try { func->numNames = 1; func->names[0] = i_importInfo->fieldUtf8; } - + m3log (module, " added function: %3d; sig: %d", index, i_typeIndex); } _catch: diff --git a/source/m3_parse.c b/source/m3_parse.c index 926579c..c11242f 100644 --- a/source/m3_parse.c +++ b/source/m3_parse.c @@ -315,7 +315,7 @@ _ (ReadLEB_u32 (& numFunctions, & i_bytes, i_end)); for (u32 f = 0; f < numFunctions; ++f) { const u8 * start = i_bytes; - + u32 size; _ (ReadLEB_u32 (& size, & i_bytes, i_end)); diff --git a/source/wasm3.h b/source/wasm3.h index cb88ac3..70791ff 100644 --- a/source/wasm3.h +++ b/source/wasm3.h @@ -196,7 +196,7 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") IM3Module * o_module, const uint8_t * const i_wasmBytes, uint32_t i_numWasmBytes); - + // Only unloaded modules need to be freed void m3_FreeModule (IM3Module i_module);