- 'common' update.

This commit is contained in:
Christoph Oelckers 2020-04-07 22:44:10 +02:00
parent 4d44682603
commit 4b8444b64d
7 changed files with 100 additions and 163 deletions

View file

@ -79,7 +79,7 @@
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
FRandom pr_exrandom; FRandom pr_exrandom("EX_Random");
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------

View file

@ -48,6 +48,11 @@ public:
FRandom (const char *name); FRandom (const char *name);
~FRandom (); ~FRandom ();
int Seed() const
{
return sfmt.u[0] + idx;
}
// Returns a random number in the range [0,255] // Returns a random number in the range [0,255]
int operator()() int operator()()
{ {

View file

@ -57,6 +57,7 @@
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
EXTERN_CVAR(Bool, strictdecorate);
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
FMemArena ClassDataAllocator(32768); // use this for all static class data that can be released in bulk when the type system is shut down. FMemArena ClassDataAllocator(32768); // use this for all static class data that can be released in bulk when the type system is shut down.

View file

@ -49,18 +49,9 @@
#include "v_font.h" #include "v_font.h"
#include "templates.h" #include "templates.h"
/*
#include "actor.h"
#include "a_pickups.h"
#include "thingdef.h"
#include "p_lnspec.h"
#include "doomstat.h"
#include "g_levellocals.h"
*/
extern FRandom pr_exrandom; extern FRandom pr_exrandom;
FMemArena FxAlloc(65536); FMemArena FxAlloc(65536);
CompileEnvironment compileEnvironment;
struct FLOP struct FLOP
{ {
@ -235,12 +226,6 @@ static PClass *FindClassType(FName name, FCompileContext &ctx)
return nullptr; return nullptr;
} }
bool isActor(PContainerType *type)
{
auto cls = PType::toClass(type);
return cls ? cls->Descriptor->IsDescendantOf(NAME_Actor) : false;
}
//========================================================================== //==========================================================================
// //
// ExpEmit // ExpEmit
@ -279,7 +264,7 @@ void ExpEmit::Reuse(VMFunctionBuilder *build)
// //
//========================================================================== //==========================================================================
static PFunction *FindBuiltinFunction(FName funcname) PFunction *FindBuiltinFunction(FName funcname)
{ {
return dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->FindSymbol(funcname, true)); return dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->FindSymbol(funcname, true));
} }
@ -1566,6 +1551,12 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED(); CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx); SAFE_RESOLVE(basex, ctx);
if (compileEnvironment.SpecialTypeCast)
{
auto result = compileEnvironment.SpecialTypeCast(this, ctx);
if (result != this) return result;
}
// first deal with the simple types // first deal with the simple types
if (ValueType == TypeError || basex->ValueType == TypeError || basex->ValueType == nullptr) if (ValueType == TypeError || basex->ValueType == TypeError || basex->ValueType == nullptr)
{ {
@ -2761,7 +2752,17 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
delete this; delete this;
return nullptr; return nullptr;
} }
if (compileEnvironment.CheckForCustomAddition)
{
auto result = compileEnvironment.CheckForCustomAddition(this, ctx);
if (result)
{
ABORT(right);
goto goon;
}
}
if (left->ValueType == TypeTextureID && right->IsInteger()) if (left->ValueType == TypeTextureID && right->IsInteger())
{ {
ValueType = TypeTextureID; ValueType = TypeTextureID;
@ -2787,7 +2788,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
// To check: It may be that this could pass in DECORATE, although setting TypeVoid here would pretty much prevent that. // To check: It may be that this could pass in DECORATE, although setting TypeVoid here would pretty much prevent that.
goto error; goto error;
} }
goon:
if (left->isConstant() && right->isConstant()) if (left->isConstant() && right->isConstant())
{ {
if (IsFloat()) if (IsFloat())
@ -5086,11 +5087,9 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
//========================================================================== //==========================================================================
// //
// The CVAR is for finding places where thinkers are created. //
// Those will require code changes in ZScript 4.0.
// //
//========================================================================== //==========================================================================
CVAR(Bool, vm_warnthinkercreation, false, 0)
static DObject *BuiltinNew(PClass *cls, int outerside, int backwardscompatible) static DObject *BuiltinNew(PClass *cls, int outerside, int backwardscompatible)
{ {
@ -5109,21 +5108,9 @@ static DObject *BuiltinNew(PClass *cls, int outerside, int backwardscompatible)
ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars()); ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars());
return nullptr; return nullptr;
} }
// Creating actors here must be outright prohibited,
if (cls->IsDescendantOf(NAME_Actor))
{
ThrowAbortException(X_OTHER, "Cannot create actors with 'new'");
return nullptr;
}
if ((vm_warnthinkercreation || !backwardscompatible) && cls->IsDescendantOf(NAME_Thinker))
{
// This must output a diagnostic warning
Printf("Using 'new' to create thinkers is deprecated.");
}
// [ZZ] validate readonly and between scope construction // [ZZ] validate readonly and between scope construction
if (outerside) FScopeBarrier::ValidateNew(cls, outerside - 1); if (outerside) FScopeBarrier::ValidateNew(cls, outerside - 1);
DObject *object; DObject *object = cls->CreateNew();
object = cls->CreateNew();
return object; return object;
} }
@ -5142,7 +5129,7 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build)
// Call DecoRandom to generate a random number. // Call DecoRandom to generate a random number.
VMFunction *callfunc; VMFunction *callfunc;
auto sym = FindBuiltinFunction(NAME_BuiltinNew); auto sym = FindBuiltinFunction(compileEnvironment.CustomBuiltinNew != NAME_None? compileEnvironment.CustomBuiltinNew : NAME_BuiltinNew);
assert(sym); assert(sym);
callfunc = sym->Variants[0].Implementation; callfunc = sym->Variants[0].Implementation;
@ -5907,7 +5894,6 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
{ {
PSymbol * sym; PSymbol * sym;
FxExpression *newex = nullptr; FxExpression *newex = nullptr;
//int num;
CHECKRESOLVED(); CHECKRESOLVED();
@ -5935,32 +5921,13 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
} }
} }
if (Identifier == NAME_Default) if (compileEnvironment.CheckSpecialIdentifier)
{ {
if (ctx.Function == nullptr) auto result = compileEnvironment.CheckSpecialIdentifier(this, ctx);
{ if (result != this) return result;
ScriptPosition.Message(MSG_ERROR, "Unable to access class defaults from constant declaration");
delete this;
return nullptr;
}
if (ctx.Function->Variants[0].SelfClass == nullptr)
{
ScriptPosition.Message(MSG_ERROR, "Unable to access class defaults from static function");
delete this;
return nullptr;
}
if (!isActor(ctx.Function->Variants[0].SelfClass))
{
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
delete this;
return nullptr;
}
FxExpression * x = new FxClassDefaults(new FxSelf(ScriptPosition), ScriptPosition);
delete this;
return x->Resolve(ctx);
} }
// Ugh, the horror. Constants need to be taken from the owning class, but members from the self class to catch invalid accesses here... // Ugh, the horror. Constants need to be taken from the owning class, but members from the self class to catch invalid accesses here...
// see if the current class (if valid) defines something with this name. // see if the current class (if valid) defines something with this name.
PSymbolTable *symtbl; PSymbolTable *symtbl;
@ -6125,22 +6092,13 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType *
PSymbolTable *symtbl; PSymbolTable *symtbl;
bool isclass = objtype->isClass(); bool isclass = objtype->isClass();
if (Identifier == NAME_Default) if (compileEnvironment.ResolveSpecialIdentifier)
{ {
if (!isActor(objtype)) auto result = compileEnvironment.ResolveSpecialIdentifier(this, object, objtype, ctx);
{ if (result != this) return result;
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
delete object;
object = nullptr;
return nullptr;
}
FxExpression * x = new FxClassDefaults(object, ScriptPosition);
object = nullptr;
delete this;
return x->Resolve(ctx);
} }
if (objtype != nullptr && (sym = objtype->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr) if (objtype != nullptr && (sym = objtype->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr)
{ {
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
@ -6588,56 +6546,6 @@ FxExpression *FxSuper::Resolve(FCompileContext& ctx)
// //
//========================================================================== //==========================================================================
FxClassDefaults::FxClassDefaults(FxExpression *X, const FScriptPosition &pos)
: FxExpression(EFX_ClassDefaults, pos)
{
obj = X;
}
FxClassDefaults::~FxClassDefaults()
{
SAFE_DELETE(obj);
}
//==========================================================================
//
//
//
//==========================================================================
FxExpression *FxClassDefaults::Resolve(FCompileContext& ctx)
{
CHECKRESOLVED();
SAFE_RESOLVE(obj, ctx);
assert(obj->ValueType->isRealPointer());
ValueType = NewPointer(obj->ValueType->toPointer()->PointedType, true);
return this;
}
//==========================================================================
//
//
//
//==========================================================================
ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build)
{
ExpEmit ob = obj->Emit(build);
ob.Free(build);
ExpEmit meta(build, REGT_POINTER);
build->Emit(OP_CLSS, meta.RegNum, ob.RegNum);
build->Emit(OP_LP, meta.RegNum, meta.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults)));
return meta;
}
//==========================================================================
//
//
//
//==========================================================================
FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos) FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos)
: FxMemberBase(EFX_GlobalVariable, mem, pos) : FxMemberBase(EFX_GlobalVariable, mem, pos)
{ {
@ -6980,19 +6888,10 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
CHECKRESOLVED(); CHECKRESOLVED();
SAFE_RESOLVE(classx, ctx); SAFE_RESOLVE(classx, ctx);
if (membervar->SymbolName == NAME_Default) if (compileEnvironment.CheckSpecialMember)
{ {
if (!classx->ValueType->isObjectPointer() auto result = compileEnvironment.CheckSpecialMember(this, ctx);
|| !static_cast<PObjectPointer *>(classx->ValueType)->PointedClass()->IsDescendantOf(NAME_Actor)) if (result != this) return result;
{
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type");
delete this;
return nullptr;
}
FxExpression * x = new FxClassDefaults(classx, ScriptPosition);
classx = nullptr;
delete this;
return x->Resolve(ctx);
} }
// [ZZ] support magic // [ZZ] support magic
@ -7630,7 +7529,7 @@ FxFunctionCall::~FxFunctionCall()
// //
//========================================================================== //==========================================================================
static bool CheckArgSize(FName fname, FArgumentList &args, int min, int max, FScriptPosition &sc) bool CheckArgSize(FName fname, FArgumentList &args, int min, int max, FScriptPosition &sc)
{ {
int s = args.Size(); int s = args.Size();
if (s < min) if (s < min)
@ -7772,6 +7671,12 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
return x->Resolve(ctx); return x->Resolve(ctx);
} }
} }
if (compileEnvironment.CheckCustomGlobalFunctions)
{
auto result = compileEnvironment.CheckCustomGlobalFunctions(this, ctx);
if (result != this) return result;
}
PClass *cls = FindClassType(MethodName, ctx); PClass *cls = FindClassType(MethodName, ctx);
if (cls != nullptr) if (cls != nullptr)
@ -8489,6 +8394,16 @@ isresolved:
return nullptr; return nullptr;
} }
} }
else
{
// Functions with no Actor usage may not be called through a pointer because they will lose their context.
if (!(afd->Variants[0].UseFlags & SUF_ACTOR))
{
ScriptPosition.Message(MSG_ERROR, "Function %s cannot be used with a non-self object", afd->SymbolName.GetChars());
delete this;
return nullptr;
}
}
} }
// do not pass the self pointer to static functions. // do not pass the self pointer to static functions.
@ -8623,6 +8538,13 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
return nullptr; return nullptr;
} }
if (compileEnvironment.ResolveSpecialFunction)
{
auto result = compileEnvironment.ResolveSpecialFunction(this, ctx);
if (!result) return nullptr;
}
CallingFunction = ctx.Function; CallingFunction = ctx.Function;
if (ArgList.Size() > 0) if (ArgList.Size() > 0)
{ {

View file

@ -49,7 +49,7 @@
#include "vmintern.h" #include "vmintern.h"
#include "c_cvars.h" #include "c_cvars.h"
struct FState; struct FState; // needed for FxConstant. Maybe move the state constructor to a subclass later?
#define CHECKRESOLVED() if (isresolved) return this; isresolved=true; #define CHECKRESOLVED() if (isresolved) return this; isresolved=true;
#define SAFE_DELETE(p) if (p!=NULL) { delete p; p=NULL; } #define SAFE_DELETE(p) if (p!=NULL) { delete p; p=NULL; }
@ -398,23 +398,6 @@ public:
}; };
//==========================================================================
//
// FxClassDefaults
//
//==========================================================================
class FxClassDefaults : public FxExpression
{
FxExpression *obj;
public:
FxClassDefaults(FxExpression *, const FScriptPosition &);
~FxClassDefaults();
FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build);
};
//========================================================================== //==========================================================================
// //
// FxConstant // FxConstant
@ -706,12 +689,11 @@ public:
class FxTypeCast : public FxExpression class FxTypeCast : public FxExpression
{ {
public:
FxExpression *basex; FxExpression *basex;
bool NoWarn; bool NoWarn;
bool Explicit; bool Explicit;
public:
FxTypeCast(FxExpression *x, PType *type, bool nowarn, bool explicitly = false); FxTypeCast(FxExpression *x, PType *type, bool nowarn, bool explicitly = false);
~FxTypeCast(); ~FxTypeCast();
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);
@ -1539,11 +1521,11 @@ public:
class FxFunctionCall : public FxExpression class FxFunctionCall : public FxExpression
{ {
FName MethodName;
FRandom *RNG; FRandom *RNG;
FArgumentList ArgList;
public: public:
FName MethodName;
FArgumentList ArgList;
FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos); FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos);
~FxFunctionCall(); ~FxFunctionCall();
@ -1712,8 +1694,6 @@ class FxVMFunctionCall : public FxExpression
bool NoVirtual; bool NoVirtual;
bool hasStringArgs = false; bool hasStringArgs = false;
FxExpression *Self; FxExpression *Self;
PFunction *Function;
FArgumentList ArgList;
// for multi assignment // for multi assignment
int AssignCount = 0; int AssignCount = 0;
TArray<ExpEmit> ReturnRegs; TArray<ExpEmit> ReturnRegs;
@ -1722,6 +1702,10 @@ class FxVMFunctionCall : public FxExpression
bool CheckAccessibility(const VersionInfo &ver); bool CheckAccessibility(const VersionInfo &ver);
public: public:
FArgumentList ArgList;
PFunction* Function;
FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual); FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual);
~FxVMFunctionCall(); ~FxVMFunctionCall();
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);
@ -2141,4 +2125,19 @@ public:
ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build);
}; };
struct CompileEnvironment
{
FxExpression* (*SpecialTypeCast)(FxTypeCast* func, FCompileContext& ctx);
bool (*CheckForCustomAddition)(FxAddSub* func, FCompileContext& ctx);
FxExpression* (*CheckSpecialIdentifier)(FxIdentifier* func, FCompileContext& ctx);
FxExpression* (*ResolveSpecialIdentifier)(FxIdentifier* func, FxExpression*& object, PContainerType* objtype, FCompileContext& ctx);
FxExpression* (*CheckSpecialMember)(FxStructMember* func, FCompileContext& ctx);
FxExpression* (*CheckCustomGlobalFunctions)(FxFunctionCall* func, FCompileContext& ctx);
bool (*ResolveSpecialFunction)(FxVMFunctionCall* func, FCompileContext& ctx);
FName CustomBuiltinNew; //override the 'new' function if some classes need special treatment.
};
extern CompileEnvironment compileEnvironment;
#endif #endif

View file

@ -38,6 +38,8 @@
#include "c_cvars.h" #include "c_cvars.h"
#include "jit.h" #include "jit.h"
CVAR(Bool, strictdecorate, false, CVAR_GLOBALCONFIG | CVAR_ARCHIVE)
struct VMRemap struct VMRemap
{ {
uint8_t altOp, kReg, kType; uint8_t altOp, kReg, kType;
@ -832,7 +834,7 @@ void FFunctionBuildList::Build()
ctx.FunctionArgs.Push(local); ctx.FunctionArgs.Push(local);
} }
FScriptPosition::StrictErrors = true;// !item.FromDecorate || strictdecorate; FScriptPosition::StrictErrors = !item.FromDecorate || strictdecorate;
item.Code = item.Code->Resolve(ctx); item.Code = item.Code->Resolve(ctx);
// If we need extra space, load the frame pointer into a register so that we do not have to call the wasteful LFP instruction more than once. // If we need extra space, load the frame pointer into a register so that we do not have to call the wasteful LFP instruction more than once.
if (item.Function->ExtraSpace > 0) if (item.Function->ExtraSpace > 0)
@ -910,7 +912,7 @@ void FFunctionBuildList::Build()
disasmdump.Flush(); disasmdump.Flush();
} }
VMFunction::CreateRegUseInfo(); VMFunction::CreateRegUseInfo();
FScriptPosition::StrictErrors = true;// strictdecorate; FScriptPosition::StrictErrors = strictdecorate;
if (FScriptPosition::ErrorCounter == 0 && Args->CheckParm("-dumpjit")) DumpJit(); if (FScriptPosition::ErrorCounter == 0 && Args->CheckParm("-dumpjit")) DumpJit();
mItems.Clear(); mItems.Clear();

View file

@ -104,3 +104,11 @@ inline float RAD2DEG(float deg)
#define SECTION_YREG "yreg" #define SECTION_YREG "yreg"
#endif #endif
// This is needed in common code, despite being Doom specific.
enum EStateUseFlags
{
SUF_ACTOR = 1,
SUF_OVERLAY = 2,
SUF_WEAPON = 4,
SUF_ITEM = 8,
};