- implemented '**' (power) operator. To ensure reliability, acustom 'pow' function will be used to calculate it.

- fixed: FxBinary::ResolveLR' check for numeric operations was incomplete. Like far too many other places it just assumed that everything with ValueType->GetRegType() == REGT_INT is a numeric type, but for names this is not the case.
This commit is contained in:
Christoph Oelckers 2016-10-17 15:17:48 +02:00
commit 938ab4ca70
10 changed files with 1033 additions and 10 deletions

View file

@ -1824,13 +1824,16 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric)
{
ValueType = TypeBool;
}
if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT)
{
ValueType = TypeSInt32;
}
else if (left->IsNumeric() && right->IsNumeric())
{
ValueType = TypeFloat64;
if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT)
{
ValueType = TypeSInt32;
}
else
{
ValueType = TypeFloat64;
}
}
else if (left->ValueType->GetRegType() == REGT_POINTER && left->ValueType == right->ValueType)
{
@ -2137,6 +2140,60 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
//
//==========================================================================
FxPow::FxPow(FxExpression *l, FxExpression *r)
: FxBinary(TK_MulMul, new FxFloatCast(l), new FxFloatCast(r))
{
}
//==========================================================================
//
//
//
//==========================================================================
FxExpression *FxPow::Resolve(FCompileContext& ctx)
{
CHECKRESOLVED();
if (!ResolveLR(ctx, true)) return NULL;
if (left->isConstant() && right->isConstant())
{
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
double v2 = static_cast<FxConstant *>(right)->GetValue().GetFloat();
return new FxConstant(g_pow(v1, v2), left->ScriptPosition);
}
return this;
}
//==========================================================================
//
//
//
//==========================================================================
ExpEmit FxPow::Emit(VMFunctionBuilder *build)
{
ExpEmit op1 = left->Emit(build);
ExpEmit op2 = right->Emit(build);
// Pow is not commutative, so either side may be constant (but not both).
assert(!op1.Konst || !op2.Konst);
op1.Free(build);
op2.Free(build);
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
ExpEmit to(build, REGT_FLOAT);
build->Emit((op1.Konst ? OP_POWF_KR : op2.Konst ? OP_POWF_RK : OP_POWF_RR), to.RegNum, op1.RegNum, op2.RegNum);
return to;
}
//==========================================================================
//
//
//
//==========================================================================
FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r)
: FxBinary(o, l, r)
{