fixed convert operations; fixed bug in fp select compilation

extensions
Steven Massey 5 years ago
parent 2b2df0c410
commit a0220ba37b

@ -198,6 +198,11 @@ bool IsRegisterAllocated (IM3Compilation o, u32 i_register)
}
bool IsRegisterTypeAllocated (IM3Compilation o, u8 i_type)
{
return IsRegisterAllocated (o, IsFpType (i_type));
}
void AllocateRegister (IM3Compilation o, u32 i_register, u16 i_stackIndex)
{ d_m3Assert (not IsRegisterAllocated (o, i_register));
o->regStackIndexPlusOne [i_register] = i_stackIndex + 1;
@ -1356,7 +1361,8 @@ _ (PreserveRegisterIfOccupied (o, type));
EmitOp (o, op);
for (u32 i = 0; i < 3; i++)
{
if (slots [i] != c_slotUnused)
if (IsValidSlot (slots [i]))
// if (slots [i] != c_slotUnused)
EmitConstant (o, slots [i]);
}
_ (PushRegister (o, type));
@ -1406,32 +1412,32 @@ M3Result Compile_Operator (IM3Compilation o, u8 i_opcode)
{
if (IsStackTopInRegister (o))
{
operation = op->operation_sr;
operation = op->operations [0];
}
else
{
_ (PreserveRegisterIfOccupied (o, op->type));
operation = op->operation_rs;
operation = op->operations [1];
}
}
else
{
if (IsStackTopInRegister (o))
{
operation = op->operation_sr; // printf ("r <- s+r\n");
operation = op->operations [0]; // printf ("r <- s+r\n");
}
else if (IsStackTopMinus1InRegister (o))
{
operation = op->operation_rs;
operation = op->operations [1];
if (not operation) // must be commutative, then
operation = op->operation_sr;
operation = op->operations [0];
// printf ("r <- r+s\n");
}
else
{
_ (PreserveRegisterIfOccupied (o, op->type));
operation = op->operation_ss; // printf ("r <- s+s\n");
operation = op->operations [2]; // printf ("r <- s+s\n");
}
}
@ -1439,26 +1445,47 @@ _ (PreserveRegisterIfOccupied (o, op->type));
{
_ (EmitOp (o, operation));
// if (op->type != c_m3Type_none)
{
_ (EmitTopSlotAndPop (o));
_ (EmitTopSlotAndPop (o));
if (op->stackOffset < 0)
_ (EmitTopSlotAndPop (o));
if (op->stackOffset < 0)
_ (EmitTopSlotAndPop (o));
if (op->type != c_m3Type_none)
_ (PushRegister (o, op->type));
}
if (op->type != c_m3Type_none)
_ (PushRegister (o, op->type));
}
else
{
result = ErrorCompile ("no operation", o, "'%s'", op->name);
result = ErrorCompile ("no operation found for opcode", o, "'%s'", op->name);
}
_catch: return result;
}
M3Result Compile_Convert (IM3Compilation o, u8 i_opcode)
{
M3Result result = c_m3Err_none;
const M3OpInfo * opInfo = & c_operations [i_opcode];
bool destInSlot = IsRegisterTypeAllocated (o, opInfo->type);
bool sourceInSlot = IsStackTopInSlot (o);
IM3Operation op = opInfo->operations [destInSlot * 2 + sourceInSlot];
_ (EmitOp (o, op));
_ (EmitTopSlotAndPop (o));
if (destInSlot)
_ (PushAllocatedSlotAndEmit (o, opInfo->type))
else
_ (PushRegister (o, opInfo->type))
_catch: return result;
}
M3Result Compile_Load_Store (IM3Compilation o, u8 i_opcode)
{
M3Result result;
@ -1468,6 +1495,11 @@ M3Result Compile_Load_Store (IM3Compilation o, u8 i_opcode)
_ (ReadLEB_u32 (& alignHint, & o->wasm, o->wasmEnd));
_ (ReadLEB_u32 (& offset, & o->wasm, o->wasmEnd));
m3log (compile, d_indent "%s (offset = %d)", get_indention_string (o), offset);
const M3OpInfo * op = & c_operations [i_opcode];
if (IsFpType (op->type))
_ (PreserveRegisterIfOccupied (o, c_m3Type_f64));
_ (Compile_Operator (o, i_opcode));
EmitConstant (o, offset);
@ -1475,12 +1507,13 @@ _ (Compile_Operator (o, i_opcode));
}
#define d_singleOp(OP) op_##OP, NULL, NULL // these aren't actually used by the compiler, just codepage decoding
#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
#define d_commutativeBinOpList(TYPE, NAME) op_##TYPE##_##NAME##_sr, NULL, op_##TYPE##_##NAME##_ss
#define d_singleOp(OP) { op_##OP, NULL, NULL, NULL } // these aren't actually used by the compiler, just codepage decoding
#define d_emptyOpList() { NULL, NULL, NULL, NULL }
#define d_unaryOpList(TYPE, NAME) { op_##TYPE##_##NAME##_r, op_##TYPE##_##NAME##_s, NULL, NULL }
#define d_binOpList(TYPE, NAME) { op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_ss, NULL }
#define d_commutativeBinOpList(TYPE, NAME) { op_##TYPE##_##NAME##_sr, NULL, op_##TYPE##_##NAME##_ss, NULL }
#define d_convertOpList(OP) { op_##OP##_r_r, op_##OP##_r_s, op_##OP##_s_r, op_##OP##_s_s }
const M3OpInfo c_operations [] =
{
@ -1495,7 +1528,7 @@ const M3OpInfo c_operations [] =
M3OP( "end", 0, none, d_emptyOpList(), Compile_Else_End ), // 0x0b
M3OP( "br", 0, none, d_singleOp (Branch), Compile_Branch ), // 0x0c
M3OP( "br_if", -1, none, op_BranchIf_r, op_BranchIf_s, NULL, Compile_Branch ), // 0x0d
M3OP( "br_if", -1, none, { op_BranchIf_r, op_BranchIf_s, NULL, NULL }, Compile_Branch ), // 0x0d
M3OP( "br_table", -1, none, d_singleOp (BranchTable), Compile_BranchTable ), // 0x0e
M3OP( "return", 0, any, d_singleOp (Return), Compile_Return ), // 0x0f
M3OP( "call", 0, any, d_singleOp (Call), Compile_Call ), // 0x10
@ -1666,65 +1699,59 @@ const M3OpInfo c_operations [] =
M3OP( "f64.max", -1, f_64, d_commutativeBinOpList (f64, Max) ), // 0xa5
M3OP( "f64.copysign", -1, f_64, d_binOpList (f64, CopySign) ), // 0xa6
M3OP( "i32.wrap/i64", 0, i_32, d_unaryOpList(i32, Wrap_i64) ), // 0xa7
M3OP( "i32.trunc_s/f32", 0, i_32, d_unaryOpList(i32, Trunc_f32) ), // 0xa8
M3OP( "i32.trunc_u/f32", 0, i_32, d_unaryOpList(u32, Trunc_f32) ), // 0xa9
M3OP( "i32.trunc_s/f64", 0, i_32, d_unaryOpList(i32, Trunc_f64) ), // 0xaa
M3OP( "i32.trunc_u/f64", 0, i_32, d_unaryOpList(u32, Trunc_f64) ), // 0xab
M3OP( "i64.extend_s/i32", 0, i_64, d_unaryOpList(i64, Extend_i32) ), // 0xac
M3OP( "i64.extend_u/i32", 0, i_64, d_unaryOpList(i64, Extend_u32) ), // 0xad
M3OP( "i64.trunc_s/f32", 0, i_64, d_unaryOpList(i64, Trunc_f32) ), // 0xae
M3OP( "i64.trunc_u/f32", 0, i_64, d_unaryOpList(u64, Trunc_f32) ), // 0xaf
M3OP( "i64.trunc_s/f64", 0, i_64, d_unaryOpList(i64, Trunc_f64) ), // 0xb0
M3OP( "i64.trunc_u/f64", 0, i_64, d_unaryOpList(u64, Trunc_f64) ), // 0xb1
M3OP( "f32.convert_s/i32", 0, f_32, d_unaryOpList(f32, Convert_i32) ), // 0xb2
M3OP( "f32.convert_u/i32", 0, f_32, d_unaryOpList(f32, Convert_u32) ), // 0xb3
M3OP( "f32.convert_s/i64", 0, f_32, d_unaryOpList(f32, Convert_i64) ), // 0xb4
M3OP( "f32.convert_u/i64", 0, f_32, d_unaryOpList(f32, Convert_u64) ), // 0xb5
M3OP( "f32.demote/f64", 0, f_32, d_unaryOpList(f32, Demote_f64) ), // 0xb6
M3OP( "f64.convert_s/i32", 0, f_64, d_unaryOpList(f64, Convert_i32) ), // 0xb7
M3OP( "f64.convert_u/i32", 0, f_64, d_unaryOpList(f64, Convert_u32) ), // 0xb8
M3OP( "f64.convert_s/i64", 0, f_64, d_unaryOpList(f64, Convert_i64) ), // 0xb9
M3OP( "f64.convert_u/i64", 0, f_64, d_unaryOpList(f64, Convert_u64) ), // 0xba
M3OP( "f64.promote/f32", 0, f_64, d_unaryOpList(f64, Promote_f32) ), // 0xbb
M3OP( "i32.reinterpret/f32", 0, i_32, d_unaryOpList(i32, Reinterpret_f32) ), // 0xbc
M3OP( "i64.reinterpret/f64", 0, i_64, d_unaryOpList(i64, Reinterpret_f64) ), // 0xbd
M3OP( "f32.reinterpret/i32", 0, f_32, d_unaryOpList(f32, Reinterpret_i32) ), // 0xbe
M3OP( "f64.reinterpret/i64", 0, f_64, d_unaryOpList(f64, Reinterpret_i64) ), // 0xbf
M3OP( "i32.wrap/i64", 0, i_32, d_unaryOpList (i32, Wrap_i64) ), // 0xa7
M3OP( "i32.trunc_s/f32", 0, i_32, d_convertOpList (i32_Trunc_f32), Compile_Convert ), // 0xa8
M3OP( "i32.trunc_u/f32", 0, i_32, d_convertOpList (u32_Trunc_f32), Compile_Convert ), // 0xa9
M3OP( "i32.trunc_s/f64", 0, i_32, d_convertOpList (i32_Trunc_f64), Compile_Convert ), // 0xaa
M3OP( "i32.trunc_u/f64", 0, i_32, d_convertOpList (u32_Trunc_f64), Compile_Convert ), // 0xab
M3OP( "i64.extend_s/i32", 0, i_64, d_unaryOpList (i64, Extend_i32) ), // 0xac
M3OP( "i64.extend_u/i32", 0, i_64, d_unaryOpList (i64, Extend_u32) ), // 0xad
M3OP( "i64.trunc_s/f32", 0, i_64, d_convertOpList (i64_Trunc_f32), Compile_Convert ), // 0xae
M3OP( "i64.trunc_u/f32", 0, i_64, d_convertOpList (u64_Trunc_f32), Compile_Convert ), // 0xaf
M3OP( "i64.trunc_s/f64", 0, i_64, d_convertOpList (i64_Trunc_f64), Compile_Convert ), // 0xb0
M3OP( "i64.trunc_u/f64", 0, i_64, d_convertOpList (u64_Trunc_f64), Compile_Convert ), // 0xb1
M3OP( "f32.convert_s/i32", 0, f_32, d_convertOpList (f32_Convert_i32), Compile_Convert ), // 0xb2
M3OP( "f32.convert_u/i32", 0, f_32, d_convertOpList (f32_Convert_u32), Compile_Convert ), // 0xb3
M3OP( "f32.convert_s/i64", 0, f_32, d_convertOpList (f32_Convert_i64), Compile_Convert ), // 0xb4
M3OP( "f32.convert_u/i64", 0, f_32, d_convertOpList (f32_Convert_u64), Compile_Convert ), // 0xb5
M3OP( "f32.demote/f64", 0, f_32, d_unaryOpList (f32, Demote_f64) ), // 0xb6
M3OP( "f64.convert_s/i32", 0, f_64, d_convertOpList (f64_Convert_i32), Compile_Convert ), // 0xb7
M3OP( "f64.convert_u/i32", 0, f_64, d_convertOpList (f64_Convert_u32), Compile_Convert ), // 0xb8
M3OP( "f64.convert_s/i64", 0, f_64, d_convertOpList (f64_Convert_i64), Compile_Convert ), // 0xb9
M3OP( "f64.convert_u/i64", 0, f_64, d_convertOpList (f64_Convert_u64), Compile_Convert ), // 0xba
M3OP( "f64.promote/f32", 0, f_64, d_unaryOpList (f64, Promote_f32) ), // 0xbb
M3OP( "i32.reinterpret/f32", 0, i_32, d_convertOpList (i32_Reinterpret_f32), Compile_Convert ), // 0xbc
M3OP( "i64.reinterpret/f64", 0, i_64, d_convertOpList (i64_Reinterpret_f64), Compile_Convert ), // 0xbd
M3OP( "f32.reinterpret/i32", 0, f_32, d_convertOpList (f32_Reinterpret_i32), Compile_Convert ), // 0xbe
M3OP( "f64.reinterpret/i64", 0, f_64, d_convertOpList (f64_Reinterpret_i64), Compile_Convert ), // 0xbf
# ifdef DEBUG // for codepage logging:
M3OP( "Const", 1, any, op_Const ),
M3OP( "Entry", 0, none, op_Entry ),
M3OP( "Compile", 0, none, op_Compile),
M3OP( "Bridge", 0, none, op_Bridge),
M3OP( "SetGlobal_s", 0, none, op_SetGlobal_s),
M3OP( "ContinueLoop", 0, none, op_ContinueLoop),
M3OP( "ContinueLoopIf", 0, none, op_ContinueLoopIf),
M3OP( "PreserveCopySlot", 0, none, op_PreserveCopySlot_64),
M3OP( "CopySlot", 0, none, op_CopySlot_64),
M3OP( "SetSlot_i32", 0, none, op_SetSlot_i32),
M3OP( "SetSlot_i64", 0, none, op_SetSlot_i64),
M3OP( "SetSlot_f32", 0, none, op_SetSlot_f32),
M3OP( "SetSlot_f64", 0, none, op_SetSlot_f64),
# define d_m3DebugOp(OP) M3OP (#OP, 0, none, op_##OP)
d_m3DebugOp (Const), d_m3DebugOp (Entry), d_m3DebugOp (Compile),
d_m3DebugOp (Bridge), d_m3DebugOp (End), d_m3DebugOp (SetGlobal_s),
M3OP( "SetRegister_i32", 0, none, op_SetRegister_i32),
M3OP( "SetRegister_i64", 0, none, op_SetRegister_i64),
M3OP( "SetRegister_f32", 0, none, op_SetRegister_f32),
M3OP( "SetRegister_f64", 0, none, op_SetRegister_f64),
d_m3DebugOp (ContinueLoop), d_m3DebugOp (ContinueLoopIf),
M3OP( "i32_BranchIf_rs", 0, none, op_i32_BranchIf_rs),
M3OP( "i32_BranchIf_ss", 0, none, op_i32_BranchIf_ss),
M3OP( "i64_BranchIf_rs", 0, none, op_i64_BranchIf_rs),
M3OP( "i64_BranchIf_ss", 0, none, op_i64_BranchIf_ss),
d_m3DebugOp (CopySlot_64), d_m3DebugOp (PreserveCopySlot_64),
d_m3DebugOp (SetSlot_i32),
d_m3DebugOp (SetSlot_i64),
d_m3DebugOp (SetSlot_f32),
d_m3DebugOp (SetSlot_f64),
d_m3DebugOp (SetRegister_i32), d_m3DebugOp (i32_BranchIf_rs),
d_m3DebugOp (SetRegister_i64), d_m3DebugOp (i32_BranchIf_ss),
d_m3DebugOp (SetRegister_f32), d_m3DebugOp (i64_BranchIf_rs),
d_m3DebugOp (SetRegister_f64), d_m3DebugOp (i64_BranchIf_ss),
M3OP( "End", 0, none, op_End ),
# endif
M3OP( "termination", 0, c_m3Type_void ) // termination for find_operation_info ()

@ -93,7 +93,7 @@ typedef struct
u16 wasmStack [c_m3MaxFunctionStackHeight];
u8 typeStack [c_m3MaxFunctionStackHeight];
// this array just contains single bit allocation flags. could be fused with the typeStack to conserve space
// OPTZ: this array just contains single bit allocation flags. could be fused with the typeStack to conserve space
u8 m3Slots [c_m3MaxFunctionStackHeight];
u16 numAllocatedExecSlots;
@ -122,10 +122,10 @@ typedef struct M3OpInfo
i8 stackOffset;
u8 type;
IM3Operation operation_sr; // top operand in register
IM3Operation operation_rs; // top operand in stack
IM3Operation operation_ss; // both operands in stack
// for most operations:
// [0]= top operand in register, [1]= top operand in stack, [2]= both operands in stack
IM3Operation operations [4];
M3Compiler compiler;
}
M3OpInfo;

@ -268,16 +268,29 @@ d_m3UnaryOp_i (u64, Popcnt, __builtin_popcountll)
d_m3UnaryOp_i (i32, Wrap_i64, OP_WRAP_I64)
#define d_m3TruncMacro(RES, REG, TYPE, NAME, FROM, OP, ...) \
d_m3Op(TYPE##_##NAME##_##FROM##_r) \
#define d_m3TruncMacro(DEST, SRC, TYPE, NAME, FROM, OP, ...) \
d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \
{ \
OP((RES), (FROM) REG, ##__VA_ARGS__); \
OP((DEST), (FROM) SRC, ##__VA_ARGS__); \
return nextOp (); \
} \
d_m3Op(TYPE##_##NAME##_##FROM##_s) \
d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \
{ \
FROM * stack = (FROM *) (_sp + immediate (i32));\
OP((RES), (* stack), ##__VA_ARGS__); \
FROM * stack = slot_ptr (FROM); \
OP((DEST), (* stack), ##__VA_ARGS__); \
return nextOp (); \
} \
d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \
{ \
TYPE * dest = slot_ptr (TYPE); \
OP((* dest), (FROM) SRC, ##__VA_ARGS__); \
return nextOp (); \
} \
d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \
{ \
FROM * stack = slot_ptr (FROM); \
TYPE * dest = slot_ptr (TYPE); \
OP((* dest), (* stack), ##__VA_ARGS__); \
return nextOp (); \
}
@ -292,7 +305,7 @@ d_m3TruncMacro(_r0, _fp0, i64, Trunc, f64, OP_I64_TRUNC_F64)
d_m3TruncMacro(_r0, _fp0, u64, Trunc, f64, OP_U64_TRUNC_F64)
#define d_m3TypeConvertOp(REG_TO, REG_FROM, TO, NAME, FROM) \
#define d_m3TypeModifyOp(REG_TO, REG_FROM, TO, NAME, FROM) \
d_m3Op(TO##_##NAME##_##FROM##_r) \
{ \
REG_TO = (TO) ((FROM) REG_FROM); \
@ -307,39 +320,84 @@ d_m3Op(TO##_##NAME##_##FROM##_s) \
}
// Int to int
d_m3TypeConvertOp(_r0, _r0, i64, Extend, i32);
d_m3TypeConvertOp(_r0, _r0, i64, Extend, u32);
d_m3TypeModifyOp (_r0, _r0, i64, Extend, i32);
d_m3TypeModifyOp (_r0, _r0, i64, Extend, u32);
// Float to float
d_m3TypeModifyOp (_fp0, _fp0, f32, Demote, f64);
d_m3TypeModifyOp (_fp0, _fp0, f64, Promote, f32);
#define d_m3TypeConvertOp(REG_TO, REG_FROM, TO, NAME, FROM) \
d_m3Op(TO##_##NAME##_##FROM##_r_r) \
{ \
REG_TO = (TO) ((FROM) REG_FROM); \
return nextOp (); \
} \
\
d_m3Op(TO##_##NAME##_##FROM##_s_r) \
{ \
slot (TO) = (TO) ((FROM) REG_FROM); \
return nextOp (); \
} \
\
d_m3Op(TO##_##NAME##_##FROM##_r_s) \
{ \
FROM from = slot (FROM); \
REG_TO = (TO) (from); \
return nextOp (); \
} \
\
d_m3Op(TO##_##NAME##_##FROM##_s_s) \
{ \
FROM from = slot (FROM); \
slot (TO) = (TO) (from); \
return nextOp (); \
}
// Int to float
d_m3TypeConvertOp(_fp0, _r0, f64, Convert, i32);
d_m3TypeConvertOp(_fp0, _r0, f64, Convert, u32);
d_m3TypeConvertOp(_fp0, _r0, f64, Convert, i64);
d_m3TypeConvertOp(_fp0, _r0, f64, Convert, u64);
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i32);
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u32);
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i64);
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u64);
d_m3TypeConvertOp(_fp0, _r0, f32, Convert, i32);
d_m3TypeConvertOp(_fp0, _r0, f32, Convert, u32);
d_m3TypeConvertOp(_fp0, _r0, f32, Convert, i64);
d_m3TypeConvertOp(_fp0, _r0, f32, Convert, u64);
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i32);
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u32);
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i64);
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u64);
// Float to float
d_m3TypeConvertOp(_fp0, _fp0, f32, Demote, f64);
d_m3TypeConvertOp(_fp0, _fp0, f64, Promote, f32);
#define d_m3ReinterpretOp(REG, TO, SRC, FROM) \
d_m3Op(TO##_Reinterpret_##FROM##_r) \
d_m3Op(TO##_Reinterpret_##FROM##_r_r) \
{ \
union { FROM c; TO t; } u; \
u.c = (FROM)SRC; \
u.c = (FROM) SRC; \
REG = u.t; \
return nextOp (); \
} \
\
d_m3Op(TO##_Reinterpret_##FROM##_s) \
d_m3Op(TO##_Reinterpret_##FROM##_r_s) \
{ \
union { FROM c; TO t; } u; \
u.c = *(FROM *) (_sp + immediate (i32)); \
u.c = slot (FROM); \
REG = u.t; \
return nextOp (); \
} \
\
d_m3Op(TO##_Reinterpret_##FROM##_s_r) \
{ \
union { FROM c; TO t; } u; \
u.c = (FROM) SRC; \
slot (TO) = u.t; \
return nextOp (); \
} \
\
d_m3Op(TO##_Reinterpret_##FROM##_s_s) \
{ \
union { FROM c; TO t; } u; \
u.c = slot (FROM); \
slot (TO) = u.t; \
return nextOp (); \
}
d_m3ReinterpretOp (_r0, i32, _fp0, f32)
@ -649,15 +707,6 @@ d_m3Op (PreserveCopySlot_64)
}
//d_m3Op (SwapRegister_i)
//{
// slot (u64) = _r0;
// _r0 = slot (u64);
//
// return nextOp ();
//}
#define d_m3SetRegisterSetSlot(TYPE, REG) \
d_m3Op (SetRegister_##TYPE) \
{ \

@ -134,13 +134,14 @@ OpInfo find_operation_info (IM3Operation i_operation)
if (oi->type != c_m3Type_void)
{
if (oi->operation_rs == i_operation or
oi->operation_sr == i_operation or
oi->operation_ss == i_operation)
for (u32 o = 0; o < 4; ++o)
{
opInfo.info = oi;
opInfo.opcode = i;
break;
if (oi->operations [o] == i_operation)
{
opInfo.info = oi;
opInfo.opcode = i;
break;
}
}
}
else break;

Loading…
Cancel
Save