- cleaned up FxCompareRel::Resolve. Also added unsigned integer support to it and FxMulDiv (these, aside from the float cast, are the only two operations where this is important.)

This commit is contained in:
Christoph Oelckers 2016-11-18 12:23:58 +01:00
parent b6801d526b
commit d9953eb3bd
2 changed files with 80 additions and 19 deletions

View file

@ -2922,9 +2922,18 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
{
assert(ValueType->GetRegType() == REGT_INT);
assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT);
if (ValueType == TypeUInt32)
{
build->Emit(Operator == '/' ? (op1.Konst ? OP_DIVU_KR : op2.Konst ? OP_DIVU_RK : OP_DIVU_RR)
: (op1.Konst ? OP_MODU_KR : op2.Konst ? OP_MODU_RK : OP_MODU_RR),
to.RegNum, op1.RegNum, op2.RegNum);
}
else
{
build->Emit(Operator == '/' ? (op1.Konst ? OP_DIV_KR : op2.Konst ? OP_DIV_RK : OP_DIV_RR)
: (op1.Konst ? OP_MOD_KR : op2.Konst ? OP_MOD_RK : OP_MOD_RR),
to.RegNum, op1.RegNum, op2.RegNum);
}
return to;
}
}
@ -3024,16 +3033,51 @@ FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r)
FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
{
CHECKRESOLVED();
if (!ResolveLR(ctx, true))
return nullptr;
if (!IsNumeric())
RESOLVE(left, ctx);
RESOLVE(right, ctx);
if (!left || !right)
{
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
delete this;
return nullptr;
}
else if (left->isConstant() && right->isConstant())
if (left->ValueType == TypeString || right->ValueType == TypeString)
{
if (left->ValueType != TypeString)
{
left = new FxStringCast(left);
left = left->Resolve(ctx);
if (left == nullptr)
{
delete this;
return nullptr;
}
}
if (right->ValueType != TypeString)
{
right = new FxStringCast(right);
right = right->Resolve(ctx);
if (right == nullptr)
{
delete this;
return nullptr;
}
}
ValueType == TypeString;
}
else if (left->IsNumeric() && right->IsNumeric())
{
Promote(ctx);
}
else
{
ScriptPosition.Message(MSG_ERROR, "Incompatible operands for relative comparison");
delete this;
return nullptr;
}
if (left->isConstant() && right->isConstant())
{
int v;
@ -3056,6 +3100,15 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
Operator == TK_Geq? v1 >= v2 :
Operator == TK_Leq? v1 <= v2 : 0;
}
else if (ValueType == TypeUInt32)
{
int v1 = static_cast<FxConstant *>(left)->GetValue().GetUInt();
int v2 = static_cast<FxConstant *>(right)->GetValue().GetUInt();
v = Operator == '<'? v1 < v2 :
Operator == '>'? v1 > v2 :
Operator == TK_Geq? v1 >= v2 :
Operator == TK_Leq? v1 <= v2 : 0;
}
else
{
int v1 = static_cast<FxConstant *>(left)->GetValue().GetInt();
@ -3069,7 +3122,7 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
delete this;
return e;
}
Promote(ctx);
CompareType = ValueType; // needs to be preserved for detection of unsigned compare.
ValueType = TypeBool;
return this;
}
@ -3124,10 +3177,10 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
assert(Operator == '<' || Operator == '>' || Operator == TK_Geq || Operator == TK_Leq);
static const VM_UBYTE InstrMap[][4] =
{
{ OP_LT_RR, OP_LTF_RR, 0 }, // <
{ OP_LE_RR, OP_LEF_RR, 1 }, // >
{ OP_LT_RR, OP_LTF_RR, 1 }, // >=
{ OP_LE_RR, OP_LEF_RR, 0 } // <=
{ OP_LT_RR, OP_LTF_RR, OP_LTU_RR, 0 }, // <
{ OP_LE_RR, OP_LEF_RR, OP_LEU_RR, 1 }, // >
{ OP_LT_RR, OP_LTF_RR, OP_LTU_RR, 1 }, // >=
{ OP_LE_RR, OP_LEF_RR, OP_LEU_RR, 0 } // <=
};
int instr, check;
ExpEmit to(build, REGT_INT);
@ -3135,8 +3188,9 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
Operator == '>' ? 1 :
Operator == TK_Geq ? 2 : 3;
instr = InstrMap[index][op1.RegType == REGT_INT ? 0 : 1];
check = InstrMap[index][2];
int mode = op1.RegType == REGT_FLOAT ? 1 : CompareType == TypeUInt32 ? 2 : 0;
instr = InstrMap[index][mode];
check = InstrMap[index][3];
if (op2.Konst)
{
instr += 1;

View file

@ -169,10 +169,16 @@ struct ExpVal
return regtype == REGT_INT ? Int : regtype == REGT_FLOAT ? int(Float) : 0;
}
unsigned GetUInt() const
{
int regtype = Type->GetRegType();
return regtype == REGT_INT ? unsigned(Int) : regtype == REGT_FLOAT ? unsigned(Float) : 0;
}
double GetFloat() const
{
int regtype = Type->GetRegType();
return regtype == REGT_INT ? double(Int) : regtype == REGT_FLOAT ? Float : 0;
return regtype == REGT_INT ? (Type == TypeUInt32? double(unsigned(Int)) : double(Int)) : regtype == REGT_FLOAT ? Float : 0;
}
void *GetPointer() const
@ -864,6 +870,7 @@ public:
class FxCompareRel : public FxBinary
{
PType *CompareType;
public:
FxCompareRel(int, FxExpression*, FxExpression*);