mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-16 17:21:10 +00:00
the MISSILE(EVEN)MORE flags still need to be accessible by ZScript for backwards compatibility.
Since these do not exist anymore an internal interface to Handle/CheckDeprecatedFlags was added.
This commit is contained in:
parent
8354c4a5c3
commit
3798fd815f
5 changed files with 190 additions and 103 deletions
|
@ -278,6 +278,8 @@ xx(BuiltinNameToClass)
|
||||||
xx(BuiltinClassCast)
|
xx(BuiltinClassCast)
|
||||||
xx(BuiltinFunctionPtrCast)
|
xx(BuiltinFunctionPtrCast)
|
||||||
xx(BuiltinFindTranslation)
|
xx(BuiltinFindTranslation)
|
||||||
|
xx(HandleDeprecatedFlags)
|
||||||
|
xx(CheckDeprecatedFlags)
|
||||||
|
|
||||||
xx(ScreenJobRunner)
|
xx(ScreenJobRunner)
|
||||||
xx(Action)
|
xx(Action)
|
||||||
|
|
|
@ -2828,83 +2828,104 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
// Special case: Assignment to a bitfield.
|
// Special case: Assignment to a bitfield.
|
||||||
IsBitWrite = Base->GetBitValue();
|
IsBitWrite = Base->GetBitValue();
|
||||||
|
if (IsBitWrite >= 0x10000)
|
||||||
|
{
|
||||||
|
// internal flags - need more here
|
||||||
|
IsBitWrite &= 0xffff;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
static const uint8_t loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP };
|
if (IsBitWrite < 64)
|
||||||
assert(Base->ValueType->GetRegType() == Right->ValueType->GetRegType());
|
|
||||||
|
|
||||||
ExpEmit pointer = Base->Emit(build);
|
|
||||||
Address = pointer;
|
|
||||||
|
|
||||||
ExpEmit result;
|
|
||||||
bool intconst = false;
|
|
||||||
int intconstval = 0;
|
|
||||||
|
|
||||||
if (Right->isConstant() && Right->ValueType->GetRegType() == REGT_INT)
|
|
||||||
{
|
{
|
||||||
intconst = true;
|
static const uint8_t loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP };
|
||||||
intconstval = static_cast<FxConstant*>(Right)->GetValue().GetInt();
|
assert(Base->ValueType->GetRegType() == Right->ValueType->GetRegType());
|
||||||
result.Konst = true;
|
|
||||||
result.RegType = REGT_INT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = Right->Emit(build);
|
|
||||||
}
|
|
||||||
assert(result.RegType <= REGT_TYPE);
|
|
||||||
|
|
||||||
if (pointer.Target)
|
ExpEmit pointer = Base->Emit(build);
|
||||||
{
|
Address = pointer;
|
||||||
if (result.Konst)
|
|
||||||
|
ExpEmit result;
|
||||||
|
bool intconst = false;
|
||||||
|
int intconstval = 0;
|
||||||
|
|
||||||
|
if (Right->isConstant() && Right->ValueType->GetRegType() == REGT_INT)
|
||||||
{
|
{
|
||||||
if (intconst) build->EmitLoadInt(pointer.RegNum, intconstval);
|
intconst = true;
|
||||||
else build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum);
|
intconstval = static_cast<FxConstant*>(Right)->GetValue().GetInt();
|
||||||
|
result.Konst = true;
|
||||||
|
result.RegType = REGT_INT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
build->Emit(Right->ValueType->GetMoveOp(), pointer.RegNum, result.RegNum);
|
result = Right->Emit(build);
|
||||||
}
|
}
|
||||||
}
|
assert(result.RegType <= REGT_TYPE);
|
||||||
else
|
|
||||||
{
|
if (pointer.Target)
|
||||||
if (result.Konst)
|
{
|
||||||
|
if (result.Konst)
|
||||||
|
{
|
||||||
|
if (intconst) build->EmitLoadInt(pointer.RegNum, intconstval);
|
||||||
|
else build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
build->Emit(Right->ValueType->GetMoveOp(), pointer.RegNum, result.RegNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (result.Konst)
|
||||||
|
{
|
||||||
|
ExpEmit temp(build, result.RegType);
|
||||||
|
if (intconst) build->EmitLoadInt(temp.RegNum, intconstval);
|
||||||
|
else build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum);
|
||||||
|
result.Free(build);
|
||||||
|
result = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsBitWrite == -1)
|
||||||
|
{
|
||||||
|
build->Emit(Base->ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
build->Emit(OP_SBIT, pointer.RegNum, result.RegNum, 1 << IsBitWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AddressRequested)
|
||||||
{
|
{
|
||||||
ExpEmit temp(build, result.RegType);
|
|
||||||
if (intconst) build->EmitLoadInt(temp.RegNum, intconstval);
|
|
||||||
else build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum);
|
|
||||||
result.Free(build);
|
result.Free(build);
|
||||||
result = temp;
|
return pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsBitWrite == -1)
|
pointer.Free(build);
|
||||||
{
|
|
||||||
build->Emit(Base->ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0));
|
if (intconst)
|
||||||
|
{ //fix int constant return for assignment
|
||||||
|
return Right->Emit(build);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
build->Emit(OP_SBIT, pointer.RegNum, result.RegNum, 1 << IsBitWrite);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AddressRequested)
|
|
||||||
{
|
|
||||||
result.Free(build);
|
|
||||||
return pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer.Free(build);
|
|
||||||
|
|
||||||
if(intconst)
|
|
||||||
{ //fix int constant return for assignment
|
|
||||||
return Right->Emit(build);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return result;
|
VMFunction* callfunc;
|
||||||
|
auto sym = FindBuiltinFunction(NAME_HandleDeprecatedFlags);
|
||||||
|
|
||||||
|
assert(sym);
|
||||||
|
callfunc = sym->Variants[0].Implementation;
|
||||||
|
|
||||||
|
FunctionCallEmitter emitters(callfunc);
|
||||||
|
emitters.AddParameter(build, Base);
|
||||||
|
emitters.AddParameter(build, Right);
|
||||||
|
emitters.AddParameterIntConst(IsBitWrite - 64);
|
||||||
|
return emitters.EmitCall(build);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2934,23 +2955,40 @@ FxExpression *FxAssignSelf::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build)
|
ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it
|
if (Assignment->IsBitWrite < 64)
|
||||||
if (!pointer.Target)
|
|
||||||
{
|
{
|
||||||
ExpEmit out(build, ValueType->GetRegType(), ValueType->GetRegCount());
|
ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it
|
||||||
if (Assignment->IsBitWrite != -1)
|
if (!pointer.Target)
|
||||||
{
|
{
|
||||||
build->Emit(OP_LBIT, out.RegNum, pointer.RegNum, 1 << Assignment->IsBitWrite);
|
ExpEmit out(build, ValueType->GetRegType(), ValueType->GetRegCount());
|
||||||
|
if (Assignment->IsBitWrite == -1)
|
||||||
|
{
|
||||||
|
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
build->Emit(OP_LBIT, out.RegNum, pointer.RegNum, 1 << Assignment->IsBitWrite);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0));
|
return pointer;
|
||||||
}
|
}
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return pointer;
|
VMFunction* callfunc;
|
||||||
|
auto sym = FindBuiltinFunction(NAME_CheckDeprecatedFlags);
|
||||||
|
|
||||||
|
assert(sym);
|
||||||
|
callfunc = sym->Variants[0].Implementation;
|
||||||
|
|
||||||
|
FunctionCallEmitter emitters(callfunc);
|
||||||
|
emitters.AddParameter(build, Assignment->Base);
|
||||||
|
emitters.AddParameterIntConst(Assignment->IsBitWrite - 64);
|
||||||
|
emitters.AddReturn(REGT_INT);
|
||||||
|
return emitters.EmitCall(build);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7728,56 +7766,73 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
ExpEmit FxStructMember::Emit(VMFunctionBuilder *build)
|
ExpEmit FxStructMember::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit obj = classx->Emit(build);
|
if (membervar->BitValue < 64 || AddressRequested)
|
||||||
assert(obj.RegType == REGT_POINTER);
|
|
||||||
|
|
||||||
if (obj.Konst)
|
|
||||||
{
|
{
|
||||||
// If the situation where we are dereferencing a constant
|
ExpEmit obj = classx->Emit(build);
|
||||||
// pointer is common, then it would probably be worthwhile
|
assert(obj.RegType == REGT_POINTER);
|
||||||
// to add new opcodes for those. But as of right now, I
|
|
||||||
// don't expect it to be a particularly common case.
|
|
||||||
ExpEmit newobj(build, REGT_POINTER);
|
|
||||||
build->Emit(OP_LKP, newobj.RegNum, obj.RegNum);
|
|
||||||
obj = newobj;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (membervar->Flags & VARF_Meta)
|
if (obj.Konst)
|
||||||
{
|
|
||||||
obj.Free(build);
|
|
||||||
ExpEmit meta(build, REGT_POINTER);
|
|
||||||
build->Emit(OP_META, meta.RegNum, obj.RegNum);
|
|
||||||
obj = meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AddressRequested)
|
|
||||||
{
|
|
||||||
if (membervar->Offset == 0)
|
|
||||||
{
|
{
|
||||||
return obj;
|
// If the situation where we are dereferencing a constant
|
||||||
|
// pointer is common, then it would probably be worthwhile
|
||||||
|
// to add new opcodes for those. But as of right now, I
|
||||||
|
// don't expect it to be a particularly common case.
|
||||||
|
ExpEmit newobj(build, REGT_POINTER);
|
||||||
|
build->Emit(OP_LKP, newobj.RegNum, obj.RegNum);
|
||||||
|
obj = newobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (membervar->Flags & VARF_Meta)
|
||||||
|
{
|
||||||
|
obj.Free(build);
|
||||||
|
ExpEmit meta(build, REGT_POINTER);
|
||||||
|
build->Emit(OP_META, meta.RegNum, obj.RegNum);
|
||||||
|
obj = meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AddressRequested)
|
||||||
|
{
|
||||||
|
if (membervar->Offset == 0)
|
||||||
|
{
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
obj.Free(build);
|
||||||
|
ExpEmit out(build, REGT_POINTER);
|
||||||
|
build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->Offset));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int offsetreg = build->GetConstantInt((int)membervar->Offset);
|
||||||
|
ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount());
|
||||||
|
|
||||||
|
if (membervar->BitValue == -1)
|
||||||
|
{
|
||||||
|
build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExpEmit out(build, REGT_POINTER);
|
||||||
|
build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, offsetreg);
|
||||||
|
build->Emit(OP_LBIT, loc.RegNum, out.RegNum, 1 << membervar->BitValue);
|
||||||
|
out.Free(build);
|
||||||
}
|
}
|
||||||
obj.Free(build);
|
obj.Free(build);
|
||||||
ExpEmit out(build, REGT_POINTER);
|
return loc;
|
||||||
build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->Offset));
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
int offsetreg = build->GetConstantInt((int)membervar->Offset);
|
|
||||||
ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount());
|
|
||||||
|
|
||||||
if (membervar->BitValue == -1)
|
|
||||||
{
|
|
||||||
build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExpEmit out(build, REGT_POINTER);
|
VMFunction* callfunc;
|
||||||
build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, offsetreg);
|
auto sym = FindBuiltinFunction(NAME_CheckDeprecatedFlags);
|
||||||
build->Emit(OP_LBIT, loc.RegNum, out.RegNum, 1 << membervar->BitValue);
|
|
||||||
out.Free(build);
|
assert(sym);
|
||||||
|
callfunc = sym->Variants[0].Implementation;
|
||||||
|
|
||||||
|
FunctionCallEmitter emitters(callfunc);
|
||||||
|
emitters.AddParameter(build, classx);
|
||||||
|
emitters.AddParameterIntConst(membervar->BitValue - 64);
|
||||||
|
emitters.AddReturn(REGT_INT);
|
||||||
|
return emitters.EmitCall(build);
|
||||||
}
|
}
|
||||||
obj.Free(build);
|
|
||||||
return loc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -920,6 +920,18 @@ void SynthesizeFlagFields()
|
||||||
{
|
{
|
||||||
cls->VMType->AddNativeField(FStringf("b%s", fl.Defs[i].name), (fl.Defs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), fl.Defs[i].structoffset, fl.Defs[i].varflags, fl.Defs[i].flagbit);
|
cls->VMType->AddNativeField(FStringf("b%s", fl.Defs[i].name), (fl.Defs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), fl.Defs[i].structoffset, fl.Defs[i].varflags, fl.Defs[i].flagbit);
|
||||||
}
|
}
|
||||||
|
else if (fl.Defs[i].flagbit == DEPF_MISSILEMORE || fl.Defs[i].flagbit == DEPF_MISSILEEVENMORE) // these need script side emulation because they have been around for many years.
|
||||||
|
{
|
||||||
|
auto field = cls->VMType->AddNativeField(FStringf("b%s", fl.Defs[i].name), TypeSInt32, 0, VARF_Native);
|
||||||
|
if (field)
|
||||||
|
{
|
||||||
|
// these are deprecated so flag accordingly with a proper message.
|
||||||
|
field->DeprecationMessage = "Use missilechancemult property instead";
|
||||||
|
field->mVersion = MakeVersion(4, 13, 0);
|
||||||
|
field->Flags |= VARF_Deprecated;
|
||||||
|
field->BitValue = fl.Defs[i].flagbit + 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,6 +361,15 @@ void HandleDeprecatedFlags(AActor *actor, int set, int index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the interface here works on object, but currently all deprecated flags affect subclasses of Actor only
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE(DObject, HandleDeprecatedFlags, HandleDeprecatedFlags)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_INT(set);
|
||||||
|
PARAM_INT(index);
|
||||||
|
HandleDeprecatedFlags(self, set, index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// CheckDeprecatedFlags
|
// CheckDeprecatedFlags
|
||||||
|
@ -429,6 +438,13 @@ int CheckDeprecatedFlags(AActor *actor, int index)
|
||||||
return false; // Any entirely unknown flag is not set
|
return false; // Any entirely unknown flag is not set
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE(DObject, CheckDeprecatedFlags, CheckDeprecatedFlags)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_INT(index);
|
||||||
|
ACTION_RETURN_INT(CheckDeprecatedFlags(self, index));
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -760,6 +760,8 @@ class Object native
|
||||||
private native static Class<Object> BuiltinNameToClass(Name nm, Class<Object> filter);
|
private native static Class<Object> BuiltinNameToClass(Name nm, Class<Object> filter);
|
||||||
private native static Object BuiltinClassCast(Object inptr, Class<Object> test);
|
private native static Object BuiltinClassCast(Object inptr, Class<Object> test);
|
||||||
private native static Function<void> BuiltinFunctionPtrCast(Function<void> inptr, voidptr newtype);
|
private native static Function<void> BuiltinFunctionPtrCast(Function<void> inptr, voidptr newtype);
|
||||||
|
private native static void HandleDeprecatedFlags(Object obj, bool set, int index);
|
||||||
|
private native static bool CheckDeprecatedFlags(Object obj, int index);
|
||||||
|
|
||||||
native static uint MSTime();
|
native static uint MSTime();
|
||||||
native static double MSTimeF();
|
native static double MSTimeF();
|
||||||
|
|
Loading…
Reference in a new issue