From a8d3eb4ca51288b348ef858c7d3b684b4c7a6a27 Mon Sep 17 00:00:00 2001 From: Steven Massey Date: Mon, 19 Apr 2021 14:35:42 -0700 Subject: [PATCH] block params mostly working --- source/m3_compile.c | 125 ++++++++++++++++++++++++++++++------------- source/m3_function.c | 23 ++++++++ source/m3_function.h | 4 ++ source/m3_info.c | 3 ++ 4 files changed, 119 insertions(+), 36 deletions(-) diff --git a/source/m3_compile.c b/source/m3_compile.c index 6f85b26..a6fac29 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -116,7 +116,7 @@ u16 GetNumBlockValuesOnStack (IM3Compilation o) return o->stackIndex - o->block.initStackIndex; } -u8 GetStackTopTypeAtOffset (IM3Compilation o, u16 i_offset) +u8 GetStackTypeFromTop (IM3Compilation o, u16 i_offset) { u8 type = c_m3Type_none; @@ -130,7 +130,7 @@ u8 GetStackTopTypeAtOffset (IM3Compilation o, u16 i_offset) u8 GetStackTopType (IM3Compilation o) { - return GetStackTopTypeAtOffset (o, 0); + return GetStackTypeFromTop (o, 0); } @@ -216,14 +216,32 @@ bool IsSlotAllocated (IM3Compilation o, u16 i_slot) } +void TouchSlot (IM3Compilation o, u16 i_slot) +{ + if (o->function) + { + // op_Entry uses this value to track and detect stack overflow + o->function->maxStackSlots = M3_MAX (o->function->maxStackSlots, i_slot + 1); + } +} + + void MarkSlotAllocated (IM3Compilation o, u16 i_slot) { d_m3Assert (o->m3Slots [i_slot] == 0); // shouldn't be already allocated o->m3Slots [i_slot] = 1; - + o->slotMaxAllocatedIndexPlusOne = M3_MAX (o->slotMaxAllocatedIndexPlusOne, i_slot + 1); + + TouchSlot (o, i_slot); } +void MarkSlotsAllocated (IM3Compilation o, u16 i_slot, u16 i_numSlots) +{ + while (i_numSlots--) + MarkSlotAllocated (o, i_slot++); +} + M3Result AllocateSlotsWithinRange (IM3Compilation o, u16 * o_slot, u8 i_type, u16 i_startSlot, u16 i_endSlot) { M3Result result = m3Err_functionStackOverflow; @@ -239,10 +257,7 @@ M3Result AllocateSlotsWithinRange (IM3Compilation o, u16 * o_slot, u8 i_type, { if (o->m3Slots [i] == 0 and o->m3Slots [i + searchOffset] == 0) { - MarkSlotAllocated (o, i); - - if (numSlots == 2) - MarkSlotAllocated (o, i + 1); + MarkSlotsAllocated (o, i, numSlots); * o_slot = i; result = m3Err_none; @@ -433,21 +448,12 @@ M3Result Push (IM3Compilation o, u8 i_type, u16 i_slot) o->wasmStack [stackIndex] = i_slot; o->typeStack [stackIndex] = i_type; - if (IsRegisterSlotAlias (i_slot)) - { - u32 regSelect = IsFpRegisterSlotAlias (i_slot); - AllocateRegister (o, regSelect, stackIndex); - } - else - { - // TODO/FIX: this should probably be in MarkSlotAllocated. Add a TouchSlot function for use in multi-returns - if (o->function) - { - // op_Entry uses this value to track and detect stack overflow - o->function->maxStackSlots = M3_MAX (o->function->maxStackSlots, i_slot + 1); - } - } - + if (IsRegisterSlotAlias (i_slot)) + { + u32 regSelect = IsFpRegisterSlotAlias (i_slot); + AllocateRegister (o, regSelect, stackIndex); + } + if (d_m3LogWasmStack) dump_type_stack (o); } else result = m3Err_functionStackOverflow; @@ -457,10 +463,14 @@ M3Result Push (IM3Compilation o, u8 i_type, u16 i_slot) M3Result PushRegister (IM3Compilation o, u8 i_type) -{ d_m3Assert ((u16) d_m3Reg0SlotAlias > (u16) d_m3MaxFunctionSlots and +{ + M3Result result = m3Err_none; d_m3Assert ((u16) d_m3Reg0SlotAlias > (u16) d_m3MaxFunctionSlots and (u16) d_m3Fp0SlotAlias > (u16) d_m3MaxFunctionSlots); - u16 location = IsFpType (i_type) ? d_m3Fp0SlotAlias : d_m3Reg0SlotAlias; d_m3Assert (i_type or IsStackPolymorphic (o)); - return Push (o, i_type, location); + u16 slot = IsFpType (i_type) ? d_m3Fp0SlotAlias : d_m3Reg0SlotAlias; d_m3Assert (i_type or IsStackPolymorphic (o)); + +_ (Push (o, i_type, slot)); + + _catch: return result; } @@ -918,7 +928,7 @@ _ (PushAllocatedSlot (o, type)) } -// TODO: update o->function->maxStackSlots +// TODO: i_tempSlot TouchSlot () M3Result MoveStackSlotsR (IM3Compilation o, u16 i_targetSlot, u16 i_stackIndex, u16 i_endStackIndex, u16 i_fillInSlot, u16 i_tempSlot) { @@ -1576,8 +1586,8 @@ _try { if (i_isIndirect) _ (Pop (o)); - u16 numArgs = i_type->numArgs; - u16 numRets = i_type->numRets; + u16 numArgs = GetFuncTypeNumParams (i_type); + u16 numRets = GetFuncTypeNumResults (i_type); u16 argTop = topSlot + (numArgs + numRets) * c_ioSlotCount; @@ -1587,17 +1597,17 @@ _ (CopyStackTopToSlot (o, argTop -= c_ioSlotCount)); _ (Pop (o)); } - if (i_type->numRets) + u16 i = 0; + while (numRets--) { - d_m3Assert(false); - - u8 type = GetSingleRetType (i_type); + u8 type = GetFuncTypeResultType (i_type, i++); _ (Push (o, type, topSlot)); u16 numSlots = GetTypeNumSlots (type); - while (numSlots--) - MarkSlotAllocated (o, topSlot++); + MarkSlotsAllocated (o, topSlot, numSlots); + + topSlot += c_ioSlotCount; } } _catch: return result; @@ -1844,14 +1854,52 @@ _ (EmitSlotNumOfStackTopAndPop (o)); IM3FuncType blockType; _ (ReadBlockType (o, & blockType)); + + u16 numParams = GetFuncTypeNumParams (blockType); + + u16 stackTop = o->stackIndex; + u16 stackIndex = stackTop - numParams; + + // make a copy of params for the potential else block + for (u16 i = 0; i < numParams; ++i) + { + u8 type = GetStackTypeFromBottom (o, stackIndex + i); + u8 slot = GetSlotForStackIndex (o, stackIndex + i); + + // duplicate params on stack; slot allocation is untouched + // but, Push allocates registers, so de-alloc first + if (IsRegisterSlotAlias (slot)) + DeallocateRegister (o, IsFpRegisterSlotAlias (slot)); + + Push (o, type, slot); + } _ (CompileBlock (o, blockType, i_opcode)); if (o->previousOpcode == c_waOp_else) { + for (u16 i = 0; i < numParams; ++i) + { + u8 slot = GetSlotForStackIndex (o, stackIndex); + u8 type = GetStackTypeFromBottom (o, stackIndex); + + if (IsRegisterSlotAlias (slot)) + AllocateRegister (o, IsFpRegisterSlotAlias (slot), stackIndex); + else if (slot >= o->slotFirstDynamicIndex) + MarkSlotsAllocated (o, slot, GetTypeNumSlots (type)); + + ++stackIndex; + } + _ (CompileElseBlock (o, pc, blockType)); } - else * pc = GetPC (o); + else + { + // unroll the unrequired param copies + o->stackIndex = stackTop; + + * pc = GetPC (o); + } } _catch: return result; } @@ -1863,7 +1911,7 @@ M3Result Compile_Select (IM3Compilation o, m3opcode_t i_opcode) u16 slots [3] = { c_slotUnused, c_slotUnused, c_slotUnused }; - u8 type = GetStackTopTypeAtOffset (o, 1); // get type of selection + u8 type = GetStackTypeFromTop (o, 1); // get type of selection IM3Operation op = NULL; @@ -2467,6 +2515,9 @@ M3Result CompileBlock (IM3Compilation o, IM3FuncType i_blockType, m3opcode_t i block->depth ++; block->opcode = i_blockOpcode; + // FIX: validate! + block->initStackIndex -= GetFuncTypeNumParams (i_blockType); + _ (CompileBlockStatements (o)); _ (ValidateBlockEnd (o)); @@ -2482,6 +2533,8 @@ _ (ResolveBlockResults (o, & o->block, false)); _ (UnwindBlockStack (o)) else _ (CommitBlockResults (o)); + +// dump_type_stack (o); } PatchBranches (o); diff --git a/source/m3_function.c b/source/m3_function.c index 6ab0afb..c39e123 100644 --- a/source/m3_function.c +++ b/source/m3_function.c @@ -26,6 +26,29 @@ bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB) return false; } +u16 GetFuncTypeNumParams (const IM3FuncType i_funcType) +{ + return i_funcType ? i_funcType->numArgs : 0; +} + + +u8 GetFuncTypeParamType (const IM3FuncType i_funcType, u16 i_index) +{ + u8 type = c_m3Type_unknown; + + if (i_funcType) + { + if (i_index < i_funcType->numArgs) + { + type = i_funcType->types [i_funcType->numRets + i_index]; + } + } + + return type; +} + + + u16 GetFuncTypeNumResults (const IM3FuncType i_funcType) { return i_funcType ? i_funcType->numRets : 0; diff --git a/source/m3_function.h b/source/m3_function.h index b183854..34695eb 100644 --- a/source/m3_function.h +++ b/source/m3_function.h @@ -29,6 +29,10 @@ typedef M3FuncType * IM3FuncType; M3Result AllocFuncType (IM3FuncType * o_functionType, u32 i_numTypes); bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB); + +u16 GetFuncTypeNumParams (const IM3FuncType i_funcType); +u8 GetFuncTypeParamType (const IM3FuncType i_funcType, u16 i_index); + u16 GetFuncTypeNumResults (const IM3FuncType i_funcType); u8 GetFuncTypeResultType (const IM3FuncType i_funcType, u16 i_index); diff --git a/source/m3_info.c b/source/m3_info.c index 15b19c2..87f8ee8 100644 --- a/source/m3_info.c +++ b/source/m3_info.c @@ -360,6 +360,9 @@ void dump_type_stack (IM3Compilation o) // printf ("%d", o->stackIndex -) for (u32 i = o->stackFirstDynamicIndex; i < o->stackIndex; ++i) { + if (i == o->block.initStackIndex) + printf (" |"); + printf (" %s", c_waCompactTypes [o->typeStack [i]]); u16 slot = o->wasmStack [i];