diff --git a/source/m3_compile.c b/source/m3_compile.c index fbd413a..57ea95b 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -488,8 +488,10 @@ M3Result AddTrapRecord (IM3Compilation o) } -void PatchBranches (IM3Compilation o) +bool PatchBranches (IM3Compilation o) { + bool patched = false; + M3CompilationScope * block = & o->block; pc_t pc = GetPC (o); @@ -502,7 +504,11 @@ void PatchBranches (IM3Compilation o) m3Free (block->patches); block->patches = next; + + patched = true; } + + return patched; } //------------------------------------------------------------------------------------------------------------------------- @@ -746,18 +752,36 @@ M3Result Compile_Else_End (IM3Compilation o, u8 i_opcode) { M3Result result = c_m3Err_none; - // function end: + // function end: if (o->block.depth == 0) { - PatchBranches (o); - - if (o->block.type) + u8 valueType = o->block.type; + + if (valueType) { -// if (GetStackTopType (o) != c_m3Type_none) + // 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 + // branches patched there. + if (IsStackTopInRegister (o)) + PatchBranches (o); + _ (ReturnStackTop (o)); } - -_ (EmitOp (o, op_End)); + else PatchBranches (o); // for no return type, branch to op_End + +_ (EmitOp (o, op_Return)); + + // B: move register to return slot for branchehs + if (valueType) + { + if (PatchBranches (o)) + { + PushRegister (o, valueType); + ReturnStackTop (o); +_ (EmitOp (o, op_Return)); + } + } } _catch: return result; @@ -940,7 +964,7 @@ _ (MoveStackTopToRegister (o)); { op = op_Branch; - if (scope->type != c_m3Type_none) + if (valueType != c_m3Type_none) _ (MoveStackTopToRegister (o)); //_ (UnwindBlockStack (o)); @@ -978,7 +1002,6 @@ _ (EnsureCodePageNumLines (o, numCodeLines)); _ (PreserveRegisterIfOccupied (o, c_m3Type_i64)); // move branch operand to a slot u16 slot = GetStackTopSlotIndex (o); - _ (Pop (o)); // OPTZ: according to spec: "forward branches that target a control instruction with a non-empty @@ -1016,7 +1039,7 @@ _ (GetBlockScope (o, & scope, target)); _ (EmitOp (o, op_ContinueLoop)); EmitPointer (o, scope->pc); - ReleaseCompilationCodePage (o); + ReleaseCompilationCodePage (o); // FIX: continueOpPage can get lost if thrown o->page = savedPage; } else _throw (c_m3Err_mallocFailedCodePage); @@ -1135,7 +1158,7 @@ _ (CompileCallArgsReturn (o, type, true)); _ (EmitOp (o, op_CallIndirect)); EmitPointer (o, o->module); - EmitPointer (o, type); // TODO: unify all types in M3Runtime + EmitPointer (o, type); // TODO: unify all types in M3Environment EmitOffset (o, execTop); EmitMemory (o); } diff --git a/source/m3_emit.c b/source/m3_emit.c index 8076072..6b50122 100644 --- a/source/m3_emit.c +++ b/source/m3_emit.c @@ -44,14 +44,14 @@ M3Result BridgeToNewPageIfNecessary (IM3Compilation o) } -void log_emit (IM3Operation i_operation) +void log_emit (IM3Compilation o, IM3Operation i_operation) { # if DEBUG OpInfo i = find_operation_info (i_operation); if (i.info) { - printf ("%s", i.info->name); + printf ("%p: %s", GetPC (o), i.info->name); } # endif } @@ -72,7 +72,7 @@ M3Result EmitOp (IM3Compilation o, IM3Operation i_operation) result = BridgeToNewPageIfNecessary (o); if (not result) - { m3logif (emit, log_emit (i_operation)) + { m3logif (emit, log_emit (o, i_operation)) EmitWord (o->page, i_operation); } } diff --git a/source/m3_env.c b/source/m3_env.c index 44435b5..2637e11 100644 --- a/source/m3_env.c +++ b/source/m3_env.c @@ -98,12 +98,13 @@ IM3Runtime m3_NewRuntime (IM3Environment i_environment, u32 i_stackSizeInBytes if (env) { + env->environment = i_environment; + m3Malloc (& env->stack, i_stackSizeInBytes); if (env->stack) { env->numStackSlots = i_stackSizeInBytes / sizeof (m3reg_t); - env->environment = i_environment; } else m3Free (env); } @@ -656,9 +657,16 @@ _ ((M3Result)Call (i_function->compiled, stack, linearMemory, d_m3OpDefaul IM3CodePage AcquireCodePage (IM3Runtime i_runtime) { if (i_runtime->pagesOpen) + { return PopCodePage (& i_runtime->pagesOpen); + } else + { + if (i_runtime->environment) + i_runtime->environment->numCodePages++; + return NewCodePage (500); // for 4kB page + } } @@ -684,16 +692,25 @@ IM3CodePage AcquireCodePageWithCapacity (IM3Runtime i_runtime, u32 i_lineCount } +u32 CountPages (IM3CodePage i_page) +{ + u32 numPages = 0; + + while (i_page) + { + ++numPages; + i_page = i_page->info.next; + } + + return numPages; +} + + + void ReleaseCodePage (IM3Runtime i_runtime, IM3CodePage i_codePage) { if (i_codePage) { -# if defined (DEBUG) -# if d_m3LogCodePages - dump_code_page (i_codePage, /* startPC: */ NULL); -# endif -# endif - IM3CodePage * list; if (NumFreeLines (i_codePage) < c_m3CodePageFreeLinesThreshold) @@ -702,6 +719,22 @@ void ReleaseCodePage (IM3Runtime i_runtime, IM3CodePage i_codePage) list = & i_runtime->pagesOpen; PushCodePage (list, i_codePage); + +# if defined (DEBUG) + u32 numOpen = CountPages (i_runtime->pagesOpen); + u32 numFull = CountPages (i_runtime->pagesFull); + u32 numTotal = i_runtime->environment ? i_runtime->environment->numCodePages : numFull + numOpen; + + m3log (code, "open-pages: %d; full-pages: %d; total: %d", numOpen, numFull, numTotal); + +// d_m3Assert (numOpen + numFull == numTotal); + +# if d_m3LogCodePages + dump_code_page (i_codePage, /* startPC: */ NULL); +# endif +# endif + + } } diff --git a/source/m3_env.h b/source/m3_env.h index 069893c..26f425c 100644 --- a/source/m3_env.h +++ b/source/m3_env.h @@ -187,6 +187,7 @@ IM3Function Module_GetFunction (IM3Module i_module, u32 //--------------------------------------------------------------------------------------------------------------------------------- typedef struct M3Environment { + u32 numCodePages; // u32 numFuncTypes; // M3FuncType * funcTypes; } diff --git a/test/run-spec-test.py b/test/run-spec-test.py index 3f74dcc..80dba43 100755 --- a/test/run-spec-test.py +++ b/test/run-spec-test.py @@ -445,10 +445,10 @@ else: "unreachable", "switch", "if", "br", "br_if", "br_table", "loop", "block", - "return", "nop", "start", + "return", "nop", "start", "unwind" #--- TODO --- - #"labels", "unwind", + #"labels", #"float_exprs", ]))