mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-05-30 16:40:58 +00:00
- scriptified A_SpawnFly.
- added support for global variables to the code generator - not the compiler, though. For the handful of entries this is needed for it may just as well be done manually. So far FLevelLocals level is the only one being exported. - fixed: The VM disassembler truncated 64 bit pointers to 15 digits because the output buffer was too small. - resolve entire FxSequences instead of aborting on the first failed entry. This allows to output all errors at once.
This commit is contained in:
parent
6aecb29995
commit
a45523fb63
15 changed files with 274 additions and 39 deletions
|
@ -5067,6 +5067,12 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
|||
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global constant\n", Identifier.GetChars());
|
||||
newex = FxConstant::MakeConstant(sym, ScriptPosition);
|
||||
}
|
||||
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
|
||||
{
|
||||
// internally defined global variable
|
||||
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global variable\n", Identifier.GetChars());
|
||||
newex = new FxGlobalVariable(static_cast<PField *>(sym), ScriptPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Invalid global identifier '%s'\n", Identifier.GetChars());
|
||||
|
@ -5303,6 +5309,72 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos)
|
||||
: FxExpression(EFX_GlobalVariable, pos)
|
||||
{
|
||||
membervar = mem;
|
||||
AddressRequested = false;
|
||||
AddressWritable = true; // must be true unless classx tells us otherwise if requested.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FxGlobalVariable::RequestAddress(bool *writable)
|
||||
{
|
||||
AddressRequested = true;
|
||||
if (writable != nullptr) *writable = AddressWritable && !(membervar->Flags & VARF_ReadOnly);
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxGlobalVariable::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
ValueType = membervar->Type;
|
||||
return this;
|
||||
}
|
||||
|
||||
ExpEmit FxGlobalVariable::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit obj(build, REGT_POINTER);
|
||||
|
||||
build->Emit(OP_LKP, obj.RegNum, build->GetConstantAddress((void*)(intptr_t)membervar->Offset, ATAG_GENERIC));
|
||||
if (AddressRequested)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount());
|
||||
|
||||
if (membervar->BitValue == -1)
|
||||
{
|
||||
int offsetreg = build->GetConstantInt(0);
|
||||
build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg);
|
||||
}
|
||||
else
|
||||
{
|
||||
build->Emit(OP_LBIT, loc.RegNum, obj.RegNum, 1 << membervar->BitValue);
|
||||
}
|
||||
obj.Free(build);
|
||||
return loc;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -5377,11 +5449,21 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
|
|||
classx = nullptr;
|
||||
return x;
|
||||
}
|
||||
else if (classx->ExprType == EFX_GlobalVariable)
|
||||
{
|
||||
auto parentfield = static_cast<FxGlobalVariable *>(classx)->membervar;
|
||||
auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset, membervar->BitValue);
|
||||
static_cast<FxGlobalVariable *>(classx)->membervar = newfield;
|
||||
classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
|
||||
auto x = classx->Resolve(ctx);
|
||||
classx = nullptr;
|
||||
return x;
|
||||
}
|
||||
else if (classx->ExprType == EFX_LocalVariable && classx->IsVector()) // vectors are a special case because they are held in registers
|
||||
{
|
||||
// since this is a vector, all potential things that may get here are single float or an xy-vector.
|
||||
auto locvar = static_cast<FxLocalVariable *>(classx);
|
||||
locvar->RegOffset = membervar->Offset / 8;
|
||||
locvar->RegOffset = int(membervar->Offset / 8);
|
||||
locvar->ValueType = membervar->Type;
|
||||
classx = nullptr;
|
||||
delete this;
|
||||
|
@ -5816,13 +5898,15 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
case NAME_Name:
|
||||
case NAME_Color:
|
||||
case NAME_Sound:
|
||||
case NAME_State:
|
||||
if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition))
|
||||
{
|
||||
PType *type = MethodName == NAME_Int ? TypeSInt32 :
|
||||
MethodName == NAME_uInt ? TypeUInt32 :
|
||||
MethodName == NAME_Double ? TypeFloat64 :
|
||||
MethodName == NAME_Name ? TypeName :
|
||||
MethodName == NAME_Color ? TypeColor : (PType*)TypeSound;
|
||||
MethodName == NAME_Color ? TypeColor :
|
||||
MethodName == NAME_State? TypeState :(PType*)TypeSound;
|
||||
|
||||
func = new FxTypeCast((*ArgList)[0], type, true, true);
|
||||
(*ArgList)[0] = nullptr;
|
||||
|
@ -6615,14 +6699,19 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build)
|
|||
FxExpression *FxSequence::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
bool fail = false;
|
||||
for (unsigned i = 0; i < Expressions.Size(); ++i)
|
||||
{
|
||||
if (nullptr == (Expressions[i] = Expressions[i]->Resolve(ctx)))
|
||||
{
|
||||
delete this;
|
||||
return nullptr;
|
||||
fail = true;
|
||||
}
|
||||
}
|
||||
if (fail)
|
||||
{
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -269,6 +269,7 @@ enum EFxType
|
|||
EFX_VectorBuiltin,
|
||||
EFX_TypeCheck,
|
||||
EFX_DynamicCast,
|
||||
EFX_GlobalVariable,
|
||||
EFX_COUNT
|
||||
};
|
||||
|
||||
|
@ -1136,6 +1137,25 @@ public:
|
|||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxGlobalVariaböe
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxGlobalVariable : public FxExpression
|
||||
{
|
||||
public:
|
||||
PField *membervar;
|
||||
bool AddressRequested;
|
||||
bool AddressWritable;
|
||||
|
||||
FxGlobalVariable(PField*, const FScriptPosition&);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
bool RequestAddress(bool *writable);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxClassMember
|
||||
|
|
|
@ -215,6 +215,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id,
|
|||
//==========================================================================
|
||||
void ParseScripts();
|
||||
void ParseAllDecorate();
|
||||
void G_InitLevelLocalsForScript();
|
||||
|
||||
void LoadActors ()
|
||||
{
|
||||
|
@ -223,6 +224,7 @@ void LoadActors ()
|
|||
timer.Reset(); timer.Clock();
|
||||
FScriptPosition::ResetErrorCounter();
|
||||
|
||||
G_InitLevelLocalsForScript();
|
||||
InitThingdef();
|
||||
FScriptPosition::StrictErrors = true;
|
||||
ParseScripts();
|
||||
|
|
|
@ -673,10 +673,16 @@ void InitThingdef()
|
|||
qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp);
|
||||
}
|
||||
|
||||
PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor));
|
||||
|
||||
PStruct *sstruct = NewStruct("Sector", nullptr);
|
||||
auto sptr = NewPointer(sstruct);
|
||||
sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget));
|
||||
|
||||
// Define some member variables we feel like exposing to the user
|
||||
PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols;
|
||||
PType *array5 = NewArray(TypeSInt32, 5);
|
||||
PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor));
|
||||
symt.AddSymbol(new PField("sector", sptr, VARF_Native, myoffsetof(AActor, Sector)));
|
||||
symt.AddSymbol(new PField(NAME_Alpha, TypeFloat64, VARF_Native, myoffsetof(AActor, Alpha)));
|
||||
symt.AddSymbol(new PField(NAME_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Yaw)));
|
||||
symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor, args)));
|
||||
|
@ -725,12 +731,14 @@ void InitThingdef()
|
|||
symt.AddSymbol(new PField("RipperLevel", TypeSInt32, VARF_Native, myoffsetof(AActor, RipperLevel)));
|
||||
symt.AddSymbol(new PField("RipLevelMin", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMin)));
|
||||
symt.AddSymbol(new PField("RipLevelMax", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMax)));
|
||||
symt.AddSymbol(new PField("special2", TypeSInt32, VARF_Native, myoffsetof(AActor, special2)));
|
||||
symt.AddSymbol(new PField(NAME_VisibleStartAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartAngle)));
|
||||
symt.AddSymbol(new PField(NAME_VisibleStartPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartPitch)));
|
||||
symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle)));
|
||||
symt.AddSymbol(new PField(NAME_VisibleEndPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndPitch)));
|
||||
symt.AddSymbol(new PField("AttackSound", TypeSound, VARF_Native, myoffsetof(AActor, AttackSound)));
|
||||
symt.AddSymbol(new PField("DeathSound", TypeSound, VARF_Native, myoffsetof(AActor, DeathSound)));
|
||||
symt.AddSymbol(new PField("SeeSound", TypeSound, VARF_Native, myoffsetof(AActor, SeeSound)));
|
||||
symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos)));
|
||||
symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel)));
|
||||
symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale)));
|
||||
|
@ -761,8 +769,11 @@ void InitThingdef()
|
|||
PSymbolTable &symt2 = RUNTIME_CLASS(DDropItem)->Symbols;
|
||||
PType *TypeDropItem = NewPointer(RUNTIME_CLASS(DDropItem));
|
||||
symt2.AddSymbol(new PField("Next", TypeDropItem, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Next)));
|
||||
symt2.AddSymbol(new PField("ItemName", TypeName, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Name)));
|
||||
symt2.AddSymbol(new PField("Name", TypeName, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Name)));
|
||||
symt2.AddSymbol(new PField("Probability", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Probability)));
|
||||
symt2.AddSymbol(new PField("Amount", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Amount)));
|
||||
symt2.AddSymbol(new PField("Amount", TypeSInt32, VARF_Native, myoffsetof(DDropItem, Amount)));
|
||||
|
||||
PSymbolTable &symt3 = RUNTIME_CLASS(DObject)->Symbols;
|
||||
symt3.AddSymbol(new PField("bDestroyed", TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(DObject, ObjectFlags), 5/*OF_EuthanizeMe*/));
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ public:
|
|||
|
||||
// Returns the constant register holding the value.
|
||||
int GetConstantInt(int val);
|
||||
int GetConstantInt(size_t val) { return GetConstantInt(int(val)); }
|
||||
int GetConstantInt(unsigned val) { return GetConstantInt(int(val)); }
|
||||
int GetConstantFloat(double val);
|
||||
int GetConstantAddress(void *ptr, VM_ATAG tag);
|
||||
int GetConstantString(FString str);
|
||||
|
|
|
@ -199,7 +199,7 @@ static int printf_wrapper(FILE *f, const char *fmt, ...)
|
|||
|
||||
void VMDumpConstants(FILE *out, const VMScriptFunction *func)
|
||||
{
|
||||
char tmp[21];
|
||||
char tmp[30];
|
||||
int i, j, k, kk;
|
||||
|
||||
if (func->KonstD != NULL && func->NumKonstD != 0)
|
||||
|
@ -239,7 +239,7 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func)
|
|||
for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk)
|
||||
{
|
||||
mysnprintf(tmp, countof(tmp), "%3d. %p:%d", k, func->KonstA[k].v, func->KonstATags()[k]);
|
||||
printf_wrapper(out, "%-20s", tmp);
|
||||
printf_wrapper(out, "%-22s", tmp);
|
||||
}
|
||||
printf_wrapper(out, "\n");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue