diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9deeeaed27..4bde29ac66 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2678,6 +2678,98 @@ ExpEmit FxBinaryInt::Emit(VMFunctionBuilder *build) // //========================================================================== +FxLtGtEq::FxLtGtEq(FxExpression *l, FxExpression *r) + : FxBinary(TK_LtGtEq, l, r) +{ + ValueType = TypeSInt32; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + if (!ResolveLR(ctx, false)) return NULL; + + if (!left->IsNumeric() || !right->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "<>= expects two numeric operands"); + delete this; + return nullptr; + } + if (left->ValueType->GetRegType() != right->ValueType->GetRegType()) + { + if (left->ValueType->GetRegType() == REGT_INT) + { + left = new FxFloatCast(left); + SAFE_RESOLVE(left, ctx); + } + if (right->ValueType->GetRegType() == REGT_INT) + { + right = new FxFloatCast(left); + SAFE_RESOLVE(left, ctx); + } + } + + else if (left->isConstant() && right->isConstant()) + { + // let's cut this short and always compare doubles. For integers the result will be exactly the same as with an integer comparison, either signed or unsigned. + auto v1 = static_cast(left)->GetValue().GetFloat(); + auto v2 = static_cast(right)->GetValue().GetFloat(); + auto e = new FxConstant(v1 < v2 ? -1 : v1 > v2 ? 1 : 0, ScriptPosition); + delete this; + return e; + } + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxLtGtEq::Emit(VMFunctionBuilder *build) +{ + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + + assert(op1.RegType == op2.RegType); + assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT); + assert(!op1.Konst || !op2.Konst); + + ExpEmit to(build, REGT_INT); + + int instr = op1.RegType == REGT_INT ? (left->ValueType == TypeUInt32? OP_LTU_RR : OP_LT_RR) : OP_LTF_RR; + if (op1.Konst) instr += 2; + if (op2.Konst) instr++; + + + build->Emit(OP_LI, to.RegNum, 1); // default to 1 + build->Emit(instr, 0, op1.RegNum, op2.RegNum); // if (left < right) + auto j1 = build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, -1); // result is -1 + auto j2 = build->Emit(OP_JMP, 1); // jump to end + build->BackpatchToHere(j1); + build->Emit(instr + OP_LE_RR - OP_LT_RR, 0, op1.RegNum, op2.RegNum); // if (left == right) + auto j3 = build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 0); // result is 0 + build->BackpatchToHere(j2); + build->BackpatchToHere(j3); + + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + FxBinaryLogical::FxBinaryLogical(int o, FxExpression *l, FxExpression *r) : FxExpression(l->ScriptPosition) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 5253252764..6bcc328301 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -769,6 +769,21 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxLtGtEq : public FxBinary +{ +public: + FxLtGtEq(FxExpression*, FxExpression*); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxBinaryLogical diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 297ac2ef0b..52d21784e3 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2547,8 +2547,10 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_XorAssign: return ModifyAssign(new FxBinaryInt(tok, new FxAssignSelf(*ast), right), left); - // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_LTGTEQ: + return new FxLtGtEq(left, right); + + // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_Concat: case PEX_Is: // more esoteric operators