mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-15 08:52:00 +00:00
- Backend update from GZDoom
adding some intrinsics to ZScript.
This commit is contained in:
parent
8806fb930b
commit
166235027c
3 changed files with 271 additions and 24 deletions
|
@ -151,7 +151,11 @@ xx(stateinfo)
|
|||
|
||||
xx(DamageFunction)
|
||||
xx(Length)
|
||||
xx(LengthSquared)
|
||||
xx(Unit)
|
||||
xx(Angle)
|
||||
xx(PlusZ)
|
||||
xx(ToVector)
|
||||
xx(Size)
|
||||
xx(Push)
|
||||
xx(Insert)
|
||||
|
|
|
@ -5127,6 +5127,23 @@ FxExpression *FxATan2::Resolve(FCompileContext &ctx)
|
|||
return this;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// The atan2 opcode only takes registers as parameters, so any constants
|
||||
// must be loaded into registers first.
|
||||
//
|
||||
//==========================================================================
|
||||
ExpEmit FxATan2::ToReg(VMFunctionBuilder* build, FxExpression* val)
|
||||
{
|
||||
if (val->isConstant())
|
||||
{
|
||||
ExpEmit reg(build, REGT_FLOAT);
|
||||
build->Emit(OP_LKF, reg.RegNum, build->GetConstantFloat(static_cast<FxConstant*>(val)->GetValue().GetFloat()));
|
||||
return reg;
|
||||
}
|
||||
return val->Emit(build);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -5143,6 +5160,61 @@ ExpEmit FxATan2::Emit(VMFunctionBuilder *build)
|
|||
return out;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
FxATan2Vec::FxATan2Vec(FxExpression* v, const FScriptPosition& pos)
|
||||
: FxExpression(EFX_ATan2Vec, pos)
|
||||
{
|
||||
vval = v;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
FxATan2Vec::~FxATan2Vec()
|
||||
{
|
||||
SAFE_DELETE(vval);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
FxExpression* FxATan2Vec::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(vval, ctx);
|
||||
|
||||
if (!vval->IsVector())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "vector value expected for parameter");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
ValueType = TypeFloat64;
|
||||
return this;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
ExpEmit FxATan2Vec::Emit(VMFunctionBuilder* build)
|
||||
{
|
||||
ExpEmit vreg = vval->Emit(build);
|
||||
vreg.Free(build);
|
||||
ExpEmit out(build, REGT_FLOAT);
|
||||
build->Emit(OP_ATAN2, out.RegNum, vreg.RegNum + 1, vreg.RegNum);
|
||||
return out;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -5278,23 +5350,6 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build)
|
|||
return emitters.EmitCall(build);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// The atan2 opcode only takes registers as parameters, so any constants
|
||||
// must be loaded into registers first.
|
||||
//
|
||||
//==========================================================================
|
||||
ExpEmit FxATan2::ToReg(VMFunctionBuilder *build, FxExpression *val)
|
||||
{
|
||||
if (val->isConstant())
|
||||
{
|
||||
ExpEmit reg(build, REGT_FLOAT);
|
||||
build->Emit(OP_LKF, reg.RegNum, build->GetConstantFloat(static_cast<FxConstant*>(val)->GetValue().GetFloat()));
|
||||
return reg;
|
||||
}
|
||||
return val->Emit(build);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -7967,11 +8022,19 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
|
||||
case NAME_ATan2:
|
||||
case NAME_VectorAngle:
|
||||
if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition))
|
||||
if (CheckArgSize(MethodName, ArgList, 1, 2, ScriptPosition))
|
||||
{
|
||||
if (ArgList.Size() == 2)
|
||||
{
|
||||
func = MethodName == NAME_ATan2 ? new FxATan2(ArgList[0], ArgList[1], ScriptPosition) : new FxATan2(ArgList[1], ArgList[0], ScriptPosition);
|
||||
ArgList[0] = ArgList[1] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
func = new FxATan2Vec(ArgList[0], ScriptPosition);
|
||||
ArgList[0] = nullptr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_New:
|
||||
|
@ -8155,6 +8218,15 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
// Note: These builtins would better be relegated to the actual type objects, instead of polluting this file, but that's a task for later.
|
||||
|
||||
// Texture builtins.
|
||||
if (Self->ValueType->isNumeric())
|
||||
{
|
||||
if (MethodName == NAME_ToVector)
|
||||
{
|
||||
Self = new FxToVector(Self);
|
||||
SAFE_RESOLVE(Self, ctx);
|
||||
return Self;
|
||||
}
|
||||
}
|
||||
else if (Self->ValueType == TypeTextureID)
|
||||
{
|
||||
if (MethodName == NAME_IsValid || MethodName == NAME_IsNull || MethodName == NAME_Exists || MethodName == NAME_SetInvalid || MethodName == NAME_SetNull)
|
||||
|
@ -8200,8 +8272,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
|
||||
else if (Self->IsVector())
|
||||
{
|
||||
// handle builtins: Vectors got 2: Length and Unit.
|
||||
if (MethodName == NAME_Length || MethodName == NAME_Unit)
|
||||
// handle builtins: Vectors got 5.
|
||||
if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Unit || MethodName == NAME_Angle)
|
||||
{
|
||||
if (ArgList.Size() > 0)
|
||||
{
|
||||
|
@ -8214,6 +8286,20 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
else if (MethodName == NAME_PlusZ && Self->IsVector3())
|
||||
{
|
||||
if (ArgList.Size() != 1)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Incorrect number of parameters in call to %s", MethodName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
auto x = new FxVectorPlusZ(Self, MethodName, ArgList[0]);
|
||||
Self = nullptr;
|
||||
ArgList[0] = nullptr;
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
else if (Self->ValueType == TypeString)
|
||||
|
@ -9190,7 +9276,23 @@ FxExpression *FxVectorBuiltin::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
SAFE_RESOLVE(Self, ctx);
|
||||
assert(Self->IsVector()); // should never be created for anything else.
|
||||
ValueType = Function == NAME_Length ? TypeFloat64 : Self->ValueType;
|
||||
switch (Function.GetIndex())
|
||||
{
|
||||
case NAME_Length:
|
||||
case NAME_LengthSquared:
|
||||
case NAME_Angle:
|
||||
ValueType = TypeFloat64;
|
||||
break;
|
||||
|
||||
case NAME_Unit:
|
||||
ValueType = Self->ValueType;
|
||||
break;
|
||||
|
||||
default:
|
||||
ValueType = TypeError;
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -9206,17 +9308,105 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
build->Emit(vecSize == 2 ? OP_LENV2 : vecSize == 3 ? OP_LENV3 : OP_LENV4, to.RegNum, op.RegNum);
|
||||
}
|
||||
else
|
||||
else if (Function == NAME_LengthSquared)
|
||||
{
|
||||
build->Emit(vecSize == 2 ? OP_DOTV2_RR : vecSize == 3 ? OP_DOTV3_RR : OP_DOTV4_RR, to.RegNum, op.RegNum, op.RegNum);
|
||||
}
|
||||
else if (Function == NAME_Unit)
|
||||
{
|
||||
ExpEmit len(build, REGT_FLOAT);
|
||||
build->Emit(vecSize == 2 ? OP_LENV2 : vecSize == 3 ? OP_LENV3 : OP_LENV4, len.RegNum, op.RegNum);
|
||||
build->Emit(vecSize == 2 ? OP_DIVVF2_RR : vecSize == 3 ? OP_DIVVF3_RR : OP_DIVVF4_RR, to.RegNum, op.RegNum, len.RegNum);
|
||||
len.Free(build);
|
||||
}
|
||||
else if (Function == NAME_Angle)
|
||||
{
|
||||
build->Emit(OP_ATAN2, to.RegNum, op.RegNum + 1, op.RegNum);
|
||||
}
|
||||
op.Free(build);
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxPlusZ
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
||||
FxVectorPlusZ::FxVectorPlusZ(FxExpression* self, FName name, FxExpression* z)
|
||||
:FxExpression(EFX_VectorBuiltin, self->ScriptPosition), Function(name), Self(self), Z(new FxFloatCast(z))
|
||||
{
|
||||
}
|
||||
|
||||
FxVectorPlusZ::~FxVectorPlusZ()
|
||||
{
|
||||
SAFE_DELETE(Self);
|
||||
SAFE_DELETE(Z);
|
||||
}
|
||||
|
||||
FxExpression* FxVectorPlusZ::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
SAFE_RESOLVE(Self, ctx);
|
||||
SAFE_RESOLVE(Z, ctx);
|
||||
assert(Self->IsVector3()); // should never be created for anything else.
|
||||
ValueType = Self->ValueType;
|
||||
return this;
|
||||
}
|
||||
|
||||
ExpEmit FxVectorPlusZ::Emit(VMFunctionBuilder* build)
|
||||
{
|
||||
ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount());
|
||||
ExpEmit op = Self->Emit(build);
|
||||
ExpEmit z = Z->Emit(build);
|
||||
|
||||
build->Emit(OP_MOVEV2, to.RegNum, op.RegNum);
|
||||
build->Emit(z.Konst ? OP_ADDF_RK : OP_ADDF_RR, to.RegNum + 2, op.RegNum + 2, z.RegNum);
|
||||
|
||||
op.Free(build);
|
||||
z.Free(build);
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxPlusZ
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
||||
FxToVector::FxToVector(FxExpression* self)
|
||||
:FxExpression(EFX_ToVector, self->ScriptPosition), Self(new FxFloatCast(self))
|
||||
{
|
||||
}
|
||||
|
||||
FxToVector::~FxToVector()
|
||||
{
|
||||
SAFE_DELETE(Self);
|
||||
}
|
||||
|
||||
FxExpression* FxToVector::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
SAFE_RESOLVE(Self, ctx);
|
||||
assert(Self->IsNumeric()); // should never be created for anything else.
|
||||
ValueType = TypeVector2;
|
||||
return this;
|
||||
}
|
||||
|
||||
ExpEmit FxToVector::Emit(VMFunctionBuilder* build)
|
||||
{
|
||||
ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount());
|
||||
ExpEmit op = Self->Emit(build);
|
||||
|
||||
build->Emit(OP_FLOP, to.RegNum, op.RegNum, FLOP_COS_DEG);
|
||||
build->Emit(OP_FLOP, to.RegNum + 1, op.RegNum, FLOP_SIN_DEG);
|
||||
|
||||
op.Free(build);
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -248,6 +248,7 @@ enum EFxType
|
|||
EFX_Conditional,
|
||||
EFX_Abs,
|
||||
EFX_ATan2,
|
||||
EFX_ATan2Vec,
|
||||
EFX_New,
|
||||
EFX_MinMax,
|
||||
EFX_Random,
|
||||
|
@ -284,6 +285,7 @@ enum EFxType
|
|||
EFX_SwitchStatement,
|
||||
EFX_CaseStatement,
|
||||
EFX_VectorValue,
|
||||
EFX_VectorPlusZ,
|
||||
EFX_VectorBuiltin,
|
||||
EFX_TypeCheck,
|
||||
EFX_DynamicCast,
|
||||
|
@ -305,6 +307,7 @@ enum EFxType
|
|||
EFX_FontCast,
|
||||
EFX_LocalArrayDeclaration,
|
||||
EFX_OutVarDereference,
|
||||
EFX_ToVector,
|
||||
EFX_COUNT
|
||||
};
|
||||
|
||||
|
@ -1201,6 +1204,18 @@ private:
|
|||
ExpEmit ToReg(VMFunctionBuilder *build, FxExpression *val);
|
||||
};
|
||||
|
||||
class FxATan2Vec : public FxExpression
|
||||
{
|
||||
FxExpression* vval;
|
||||
|
||||
public:
|
||||
|
||||
FxATan2Vec(FxExpression* y, const FScriptPosition& pos);
|
||||
~FxATan2Vec();
|
||||
FxExpression* Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder* build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -1598,6 +1613,44 @@ public:
|
|||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxPlusZ
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxVectorPlusZ : public FxExpression
|
||||
{
|
||||
FName Function;
|
||||
FxExpression* Self;
|
||||
FxExpression* Z;
|
||||
|
||||
public:
|
||||
|
||||
FxVectorPlusZ(FxExpression* self, FName name, FxExpression*);
|
||||
~FxVectorPlusZ();
|
||||
FxExpression* Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder* build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxPlusZ
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxToVector : public FxExpression
|
||||
{
|
||||
FxExpression* Self;
|
||||
|
||||
public:
|
||||
|
||||
FxToVector(FxExpression* self);
|
||||
~FxToVector();
|
||||
FxExpression* Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder* build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxVectorBuiltin
|
||||
|
|
Loading…
Reference in a new issue