From 687a2ab20f8ec3b13ebb36730549a08bf4d0c0d8 Mon Sep 17 00:00:00 2001 From: Steven Massey Date: Tue, 3 Dec 2019 15:07:58 -0800 Subject: [PATCH] work in progress: br_table, fp.select --- source/m3_compile.c | 123 +++++++++++++++++++++++++++++--------------- source/m3_compile.h | 1 + source/m3_exec.h | 67 ++++++++++++++++++++---- source/m3_info.c | 29 +++++++---- 4 files changed, 159 insertions(+), 61 deletions(-) diff --git a/source/m3_compile.c b/source/m3_compile.c index efcf8a9..c214f68 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -130,6 +130,30 @@ u8 GetStackTopType (IM3Compilation o) } +u8 GetStackType (IM3Compilation o, u16 i_offset) +{ + u8 type = c_m3Type_none; + + ++i_offset; + if (o->stackIndex > i_offset) + type = o->typeStack [o->stackIndex - i_offset]; + + return type; +} + + +u8 GetBlockType (IM3Compilation o) +{ + return o->block.type; +} + + +bool BlockHasType (IM3Compilation o) +{ + return GetBlockType (o) != c_m3Type_none; +} + + bool IsStackTopTypeInt (IM3Compilation o) { return IsIntType (GetStackTopType (o)); @@ -141,6 +165,10 @@ bool IsStackTopTypeFp (IM3Compilation o) return IsFpType (GetStackTopType (o)); } +i16 GetNumBlockValues (IM3Compilation o) +{ + return o->stackIndex - o->block.initStackIndex; +} bool IsStackTopInRegister (IM3Compilation o) { @@ -368,6 +396,8 @@ void PushRegister (IM3Compilation o, u8 i_m3Type) M3Result Pop (IM3Compilation o) { + // TODO: multivalue changes this constraint, but this should check underrunning the current block? + M3Result result = c_m3Err_none; if (o->stackIndex) @@ -848,14 +878,14 @@ M3Result Compile_Branch (IM3Compilation o, u8 i_opcode) M3Result result; u32 depth; -_ (ReadLEB_u32 (& depth, & o->wasm, o->wasmEnd)); - -// printf ("depth: %d \n", depth); +_ (ReadLEB_u32 (& depth, & o->wasm, o->wasmEnd)); // printf ("depth: %d \n", depth); + IM3CompilationScope scope; _ (GetBlockScope (o, & scope, depth)); IM3Operation op; + // branch target is a loop (continue) if (scope->opcode == c_waOp_loop) { if (i_opcode == c_waOp_branchIf) @@ -902,18 +932,23 @@ M3Result Compile_BranchTable (IM3Compilation o, u8 i_opcode) { M3Result result; + _throw ("branching needs more work"); + _try { + u32 targetCount; _ (ReadLEB_u32 (& targetCount, & o->wasm, o->wasmEnd)); u32 numCodeLines = targetCount + 3; // 3 => IM3Operation + target_count + default_target - _ (EnsureCodePageNumLines (o, numCodeLines)); -_ (MoveStackTopToRegister (o)); + // MoveStackTopToSlot (); // move stack top to slot, if necessary _ (Pop (o)); -_ (PreserveRegisters (o)); + if (BlockHasType (o) and GetNumBlockValues (o) > 0) + { +_ (MoveStackTopToRegister (o)); + } _ (EmitOp (o, op_BranchTable)); EmitConstant (o, targetCount); @@ -936,7 +971,7 @@ _ (GetBlockScope (o, & scope, target)); IM3BranchPatch prev_patch = scope->patches; _ (m3Alloc (& scope->patches, M3BranchPatch, 1)); - scope->patches->location = (pc_t*)ReservePointer (o); + scope->patches->location = (pc_t *) ReservePointer (o); scope->patches->next = prev_patch; } } @@ -1121,8 +1156,8 @@ _ (EmitTopSlotAndPop (o)); i32 stackIndex = o->stackIndex; - pc_t * preservations = (pc_t*)ReservePointer (o); - pc_t * pc = (pc_t*)ReservePointer (o); + pc_t * preservations = (pc_t *) ReservePointer (o); + pc_t * pc = (pc_t *) ReservePointer (o); u8 blockType; _ (ReadBlockType (o, & blockType)); @@ -1143,48 +1178,51 @@ _ (Compile_ElseBlock (o, pc, blockType)); } _catch: return result; } -static const IM3Operation ops_Select_i [] = { op_Select_i64_ssr, op_Select_i64_srs, op_Select_i64_rss, op_Select_i64_sss }; -static const IM3Operation ops_Select_f [] = { op_Select_f64_ssr, op_Select_f64_srs, op_Select_f64_rss, op_Select_f64_sss }; M3Result Compile_Select (IM3Compilation o, u8 i_opcode) { + static const IM3Operation selectOps [2] [4] = { { op_Select_i32_rss, op_Select_i32_srs, op_Select_i32_ssr, op_Select_i32_sss }, + { op_Select_i64_rss, op_Select_i64_srs, op_Select_i64_ssr, op_Select_i64_sss } }; + M3Result result = c_m3Err_none; u16 slots [3] = { 0xffff, 0xffff, 0xffff }; - int opIdx = 3; // op_Select_*_sss - - u8 type = 0; - for (u32 i = 0; i < 3; i++) + u8 type = GetStackType (o, 1); // get type of selection + + if (IsFpType (type)) + _throw ("FP select unimplemented"); // smassey: working on this. fp select is a tad more complex than int case. + + if (type != c_m3Type_none) { - if (IsStackTopInRegister (o)) - opIdx = i; - else - slots [i] = GetStackTopExecSlot (o); + int opIndex = 3; // op_Select_*_sss - type = GetStackTopType (o); -_ (Pop (o)); - } + for (u32 i = 0; i < 3; i++) + { + if (IsStackTopInRegister (o)) + opIndex = i; + else + slots [i] = GetStackTopExecSlot (o); - // this operation doesn't consume a register, so might have to protected its contents - if (opIdx == 3) { -_ (PreserveRegisterIfOccupied (o, type)); - } +_ (Pop (o)); + } - if (IsIntType (type)) { -_ (EmitOp (o, ops_Select_i[opIdx])); - } else { -_ (EmitOp (o, ops_Select_f[opIdx])); - } + // 'sss' operation doesn't consume a register, so might have to protected its contents + if (opIndex == 3) { +_ (PreserveRegisterIfOccupied (o, type)); + } + + EmitOp (o, selectOps [type] [opIndex]); + for (u32 i = 0; i < 3; i++) + { + if (slots [i] != 0xffff) + EmitConstant (o, slots [i]); + } - for (u32 i = 0; i < 3; i++) - { - if (slots [i] != 0xffff) - EmitConstant (o, slots [i]); + PushRegister (o, type); } - - PushRegister (o, type); + else result = c_m3Err_functionStackUnderrun; _catch: return result; } @@ -1293,6 +1331,8 @@ _ (Compile_Operator (o, i_opcode)); _catch: return result; } + +#define d_singleOp(OP) OP, NULL, NULL // these aren't actually used by the compiler, just codepage logging #define d_emptyOpList() NULL, NULL, NULL #define d_unaryOpList(TYPE, NAME) op_##TYPE##_##NAME##_r, op_##TYPE##_##NAME##_s, NULL #define d_binOpList(TYPE, NAME) op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_ss @@ -1311,9 +1351,9 @@ const M3OpInfo c_operations [] = M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, // 0x06 - 0x0a M3OP( "end", 0, none, d_emptyOpList(), Compile_Else_End ), // 0x0b - M3OP( "br", 0, none, d_emptyOpList(), Compile_Branch ), // 0x0c + M3OP( "br", 0, none, d_singleOp (op_Branch), Compile_Branch ), // 0x0c M3OP( "br_if", -1, none, d_emptyOpList(), Compile_Branch ), // 0x0d - M3OP( "br_table", -1, none, d_emptyOpList(), Compile_BranchTable ), // 0x0e + M3OP( "br_table", -1, none, d_singleOp (op_BranchTable), Compile_BranchTable ), // 0x0e M3OP( "return", 0, any, d_emptyOpList(), Compile_Return ), // 0x0f M3OP( "call", 0, any, d_emptyOpList(), Compile_Call ), // 0x10 M3OP( "call_indirect", 0, any, d_emptyOpList(), Compile_CallIndirect ), // 0x11 @@ -1517,8 +1557,6 @@ const M3OpInfo c_operations [] = M3OP( "Const", 1, any, op_Const ), M3OP( "Entry", 0, none, op_Entry ), M3OP( "unreachable", 0, none, op_Unreachable ), - M3OP( "br", 0, none, op_Branch ), - M3OP( "br_table", 0, none, op_BranchTable ), M3OP( "Call", 0, none, op_Call), M3OP( "Compile", 0, none, op_Compile), @@ -1560,6 +1598,9 @@ M3Result Compile_BlockStatements (IM3Compilation o) result = (* compiler) (o, opcode); else result = c_m3Err_noCompiler; + +// if (opcode == c_waOp_branch or opcode == c_waOp_branchTable) + o->previousOpcode = opcode; // m3logif (stack, dump_type_stack (o)) diff --git a/source/m3_compile.h b/source/m3_compile.h index 060afc0..faeaef7 100644 --- a/source/m3_compile.h +++ b/source/m3_compile.h @@ -33,6 +33,7 @@ enum c_waOp_else = 0x05, c_waOp_end = 0x0b, c_waOp_branch = 0x0c, + c_waOp_branchTable = 0x0e, c_waOp_branchIf = 0x0d, c_waOp_getLocal = 0x20, c_waOp_setLocal = 0x21, diff --git a/source/m3_exec.h b/source/m3_exec.h index 2f42cf3..8524d0c 100644 --- a/source/m3_exec.h +++ b/source/m3_exec.h @@ -365,8 +365,8 @@ d_m3OpDecl (If_r) d_m3OpDecl (If_s) -#define d_m3Select(TYPE, REG) \ -d_m3Op (Select_##TYPE##_ssr) \ +#define d_m3Select_i(TYPE, REG) \ +d_m3Op (Select_##TYPE##_rss) \ { \ i32 condition = (i32) _r0; \ \ @@ -390,7 +390,7 @@ d_m3Op (Select_##TYPE##_srs) \ return nextOp (); \ } \ \ -d_m3Op (Select_##TYPE##_rss) \ +d_m3Op (Select_##TYPE##_ssr) \ { \ i32 condition = slot (i32); \ \ @@ -414,10 +414,54 @@ d_m3Op (Select_##TYPE##_sss) \ return nextOp (); \ } -d_m3Select (i32, _r0) -d_m3Select (i64, _r0) -d_m3Select (f32, _fp0) -d_m3Select (f64, _fp0) + +d_m3Select_i (i32, _r0) +d_m3Select_i (i64, _r0) + + +#define d_m3Select_f(TYPE, REG, LABEL, SELECTOR) \ +d_m3Op (Select_##TYPE##_##LABEL##ss) \ +{ \ + i32 condition = (i32) SELECTOR; \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + return nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_##LABEL##rs) \ +{ \ + i32 condition = (i32) SELECTOR; \ + \ + TYPE operand2 = (TYPE) REG; \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + return nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_##LABEL##sr) \ +{ \ + i32 condition = (i32) SELECTOR; \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = (TYPE) REG; \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + return nextOp (); \ +} + + +d_m3Select_f (f32, _fp0, r, _r0) +d_m3Select_f (f32, _fp0, s, slot (i32)) + +d_m3Select_f (f64, _fp0, r, _r0) +d_m3Select_f (f64, _fp0, s, slot (i32)) d_m3Op (Return) @@ -454,15 +498,16 @@ d_m3Op (BranchIf) d_m3Op (BranchTable) { - i32 index = (i32) _r0; + i32 branchIndex = slot (i32); // branch index is always in a slot + u32 numTargets = immediate (u32); pc_t * branches = (pc_t *) _pc; - if (index < 0 or index > numTargets) - index = numTargets; // the default index + if (branchIndex < 0 or branchIndex > numTargets) + branchIndex = numTargets; // the default index - return jumpOp (branches [index]); + return jumpOp (branches [branchIndex]); } diff --git a/source/m3_info.c b/source/m3_info.c index 4e52346..8e0cff0 100644 --- a/source/m3_info.c +++ b/source/m3_info.c @@ -168,17 +168,28 @@ void DecodeOperation (char * o_string, u8 i_opcode, IM3OpInfo i_opInfo, pc_t * #define fetch(TYPE) (*(TYPE *) (pc++)) i32 offset; - u64 value; - - switch (i_opcode) + + if (i_opcode == c_waOp_branchTable) { - case 0xbf+1: - { - value = fetch (u64); offset = fetch (i32); - sprintf (o_string, " slot [%d] = %" PRIu64, offset, value); + m3reg_t targets = fetch (m3reg_t); + + char str [1000]; - break; + for (m3reg_t i = 0; i name, infoString); + m3log (code, "%p | %20s %s", pc - 1, i.info->name, infoString); } // else break; }