mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
- added readonly pointers. They need to be defined with 'readonly<classtype>'. These are significantly different from declaring a field readonly in that they do not disallow modification of the variable itself but what it points to. For the actor defaults this is necessary to prevent accidental modification. A readonly pointer is actually a different type than a regular pointer.
- fixed code generation for dynamic cast. It was missing the jump instruction after the compare.
This commit is contained in:
parent
ca878b5e6b
commit
24925c88a8
7 changed files with 47 additions and 20 deletions
|
@ -1467,7 +1467,7 @@ END_POINTERS
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PPointer::PPointer()
|
PPointer::PPointer()
|
||||||
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL)
|
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL), IsConst(false)
|
||||||
{
|
{
|
||||||
mDescriptiveName = "NullPointer";
|
mDescriptiveName = "NullPointer";
|
||||||
SetOps();
|
SetOps();
|
||||||
|
@ -1479,10 +1479,10 @@ PPointer::PPointer()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PPointer::PPointer(PType *pointsat)
|
PPointer::PPointer(PType *pointsat, bool isconst)
|
||||||
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(pointsat)
|
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(pointsat), IsConst(isconst)
|
||||||
{
|
{
|
||||||
mDescriptiveName.Format("Pointer<%s>", pointsat->DescriptiveName());
|
mDescriptiveName.Format("Pointer<%s%s>", pointsat->DescriptiveName(), isconst? "readonly " : "");
|
||||||
SetOps();
|
SetOps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1570,14 +1570,14 @@ bool PPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PPointer *NewPointer(PType *type)
|
PPointer *NewPointer(PType *type, bool isconst)
|
||||||
{
|
{
|
||||||
size_t bucket;
|
size_t bucket;
|
||||||
PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)type, 0, &bucket);
|
PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, &bucket);
|
||||||
if (ptype == NULL)
|
if (ptype == NULL)
|
||||||
{
|
{
|
||||||
ptype = new PPointer(type);
|
ptype = new PPointer(type);
|
||||||
TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)type, 0, bucket);
|
TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, bucket);
|
||||||
}
|
}
|
||||||
return static_cast<PPointer *>(ptype);
|
return static_cast<PPointer *>(ptype);
|
||||||
}
|
}
|
||||||
|
|
|
@ -535,9 +535,10 @@ class PPointer : public PBasicType
|
||||||
HAS_OBJECT_POINTERS;
|
HAS_OBJECT_POINTERS;
|
||||||
public:
|
public:
|
||||||
PPointer();
|
PPointer();
|
||||||
PPointer(PType *pointsat);
|
PPointer(PType *pointsat, bool isconst = false);
|
||||||
|
|
||||||
PType *PointedType;
|
PType *PointedType;
|
||||||
|
bool IsConst;
|
||||||
|
|
||||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
@ -877,7 +878,7 @@ PVector *NewVector(unsigned int size);
|
||||||
PMap *NewMap(PType *keytype, PType *valuetype);
|
PMap *NewMap(PType *keytype, PType *valuetype);
|
||||||
PArray *NewArray(PType *type, unsigned int count);
|
PArray *NewArray(PType *type, unsigned int count);
|
||||||
PDynArray *NewDynArray(PType *type);
|
PDynArray *NewDynArray(PType *type);
|
||||||
PPointer *NewPointer(PType *type);
|
PPointer *NewPointer(PType *type, bool isconst = false);
|
||||||
PClassPointer *NewClassPointer(PClass *restrict);
|
PClassPointer *NewClassPointer(PClass *restrict);
|
||||||
PEnum *NewEnum(FName name, PTypeBase *outer);
|
PEnum *NewEnum(FName name, PTypeBase *outer);
|
||||||
PStruct *NewStruct(FName name, PTypeBase *outer);
|
PStruct *NewStruct(FName name, PTypeBase *outer);
|
||||||
|
|
|
@ -241,6 +241,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source)
|
||||||
auto fromtype = static_cast<PPointer *>(source);
|
auto fromtype = static_cast<PPointer *>(source);
|
||||||
auto totype = static_cast<PPointer *>(dest);
|
auto totype = static_cast<PPointer *>(dest);
|
||||||
if (fromtype == nullptr) return true;
|
if (fromtype == nullptr) return true;
|
||||||
|
if (totype->IsConst && !fromtype->IsConst) return false;
|
||||||
if (fromtype == totype) return true;
|
if (fromtype == totype) return true;
|
||||||
if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
|
if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
|
||||||
{
|
{
|
||||||
|
@ -3852,8 +3853,7 @@ ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build)
|
||||||
FxDynamicCast::FxDynamicCast(PClass * cls, FxExpression *r)
|
FxDynamicCast::FxDynamicCast(PClass * cls, FxExpression *r)
|
||||||
: FxExpression(EFX_DynamicCast, r->ScriptPosition)
|
: FxExpression(EFX_DynamicCast, r->ScriptPosition)
|
||||||
{
|
{
|
||||||
expr = new FxTypeCast(r, NewPointer(RUNTIME_CLASS(DObject)), true, true);
|
expr = r;
|
||||||
ValueType = NewPointer(cls);
|
|
||||||
CastType = cls;
|
CastType = cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3878,6 +3878,15 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
SAFE_RESOLVE(expr, ctx);
|
SAFE_RESOLVE(expr, ctx);
|
||||||
|
bool constflag = expr->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer *>(expr->ValueType)->IsConst;
|
||||||
|
expr = new FxTypeCast(expr, NewPointer(RUNTIME_CLASS(DObject), constflag), true, true);
|
||||||
|
expr = expr->Resolve(ctx);
|
||||||
|
if (expr == nullptr)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
ValueType = NewPointer(CastType, constflag);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3903,7 +3912,8 @@ ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build)
|
||||||
|
|
||||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
|
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
|
||||||
build->Emit(OP_RESULT, 0, REGT_INT, check.RegNum);
|
build->Emit(OP_RESULT, 0, REGT_INT, check.RegNum);
|
||||||
auto patch = build->Emit(OP_EQ_K, 0, check.RegNum, build->GetConstantInt(0));
|
build->Emit(OP_EQ_K, 0, check.RegNum, build->GetConstantInt(0));
|
||||||
|
auto patch = build->Emit(OP_JMP, 0);
|
||||||
build->Emit(OP_LKP, out.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT));
|
build->Emit(OP_LKP, out.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT));
|
||||||
build->BackpatchToHere(patch);
|
build->BackpatchToHere(patch);
|
||||||
return out;
|
return out;
|
||||||
|
@ -5439,7 +5449,8 @@ FxStructMember::~FxStructMember()
|
||||||
bool FxStructMember::RequestAddress(bool *writable)
|
bool FxStructMember::RequestAddress(bool *writable)
|
||||||
{
|
{
|
||||||
AddressRequested = true;
|
AddressRequested = true;
|
||||||
if (writable != nullptr) *writable = AddressWritable && !(membervar->Flags & VARF_ReadOnly);
|
if (writable != nullptr) *writable = (AddressWritable && !(membervar->Flags & VARF_ReadOnly) &&
|
||||||
|
(!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast<PPointer*>(classx->ValueType)->IsConst));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -668,6 +668,7 @@ type_name(X) ::= type_name1(A).
|
||||||
NEW_AST_NODE(BasicType, type, A);
|
NEW_AST_NODE(BasicType, type, A);
|
||||||
type->Type = (EZCCBuiltinType)A.Int;
|
type->Type = (EZCCBuiltinType)A.Int;
|
||||||
type->UserType = NULL;
|
type->UserType = NULL;
|
||||||
|
type->isconst = false;
|
||||||
X = type;
|
X = type;
|
||||||
}
|
}
|
||||||
type_name(X) ::= IDENTIFIER(A). /* User-defined type (struct, enum, or class) */
|
type_name(X) ::= IDENTIFIER(A). /* User-defined type (struct, enum, or class) */
|
||||||
|
@ -676,14 +677,27 @@ type_name(X) ::= IDENTIFIER(A). /* User-defined type (struct, enum, or class)
|
||||||
NEW_AST_NODE(Identifier, id, A);
|
NEW_AST_NODE(Identifier, id, A);
|
||||||
type->Type = ZCC_UserType;
|
type->Type = ZCC_UserType;
|
||||||
type->UserType = id;
|
type->UserType = id;
|
||||||
|
type->isconst = false;
|
||||||
id->Id = A.Name();
|
id->Id = A.Name();
|
||||||
X = type;
|
X = type;
|
||||||
}
|
}
|
||||||
|
type_name(X) ::= READONLY LT IDENTIFIER(A) GT.
|
||||||
|
{
|
||||||
|
NEW_AST_NODE(BasicType, type, A);
|
||||||
|
NEW_AST_NODE(Identifier, id, A);
|
||||||
|
type->Type = ZCC_UserType;
|
||||||
|
type->UserType = id;
|
||||||
|
type->isconst = true;
|
||||||
|
id->Id = A.Name();
|
||||||
|
X = type;
|
||||||
|
}
|
||||||
|
|
||||||
type_name(X) ::= DOT dottable_id(A).
|
type_name(X) ::= DOT dottable_id(A).
|
||||||
{
|
{
|
||||||
NEW_AST_NODE(BasicType, type, A);
|
NEW_AST_NODE(BasicType, type, A);
|
||||||
type->Type = ZCC_UserType;
|
type->Type = ZCC_UserType;
|
||||||
type->UserType = A;
|
type->UserType = A;
|
||||||
|
type->isconst = false;
|
||||||
X = type;
|
X = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,7 +712,7 @@ type_name(X) ::= DOT dottable_id(A).
|
||||||
%type type_list {ZCC_Type *}
|
%type type_list {ZCC_Type *}
|
||||||
%type type_list_or_void {ZCC_Type *}
|
%type type_list_or_void {ZCC_Type *}
|
||||||
%type type_or_array {ZCC_Type *}
|
%type type_or_array {ZCC_Type *}
|
||||||
%type class_restrictor {ZCC_Identifier *}
|
%type class_restrictor {ZCC_Identifier *}
|
||||||
%type array_size{ZCC_Expression *}
|
%type array_size{ZCC_Expression *}
|
||||||
%type array_size_expr{ZCC_Expression *}
|
%type array_size_expr{ZCC_Expression *}
|
||||||
|
|
||||||
|
|
|
@ -1481,16 +1481,16 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt)
|
||||||
if (sym == nullptr && symt != &GlobalSymbols) sym = GlobalSymbols.FindSymbolInTable(type->UserType->Id, table);
|
if (sym == nullptr && symt != &GlobalSymbols) sym = GlobalSymbols.FindSymbolInTable(type->UserType->Id, table);
|
||||||
if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
|
if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
|
||||||
{
|
{
|
||||||
auto type = static_cast<PSymbolType *>(sym)->Type;
|
auto ptype = static_cast<PSymbolType *>(sym)->Type;
|
||||||
if (type->IsKindOf(RUNTIME_CLASS(PEnum)))
|
if (ptype->IsKindOf(RUNTIME_CLASS(PEnum)))
|
||||||
{
|
{
|
||||||
return TypeSInt32; // hack this to an integer until we can resolve the enum mess.
|
return TypeSInt32; // hack this to an integer until we can resolve the enum mess.
|
||||||
}
|
}
|
||||||
if (type->IsKindOf(RUNTIME_CLASS(PClass)))
|
if (ptype->IsKindOf(RUNTIME_CLASS(PClass)))
|
||||||
{
|
{
|
||||||
return NewPointer(type);
|
return NewPointer(ptype, type->isconst);
|
||||||
}
|
}
|
||||||
return type;
|
return ptype;
|
||||||
}
|
}
|
||||||
Error(type, "Unable to resolve %s as type.", FName(type->UserType->Id).GetChars());
|
Error(type, "Unable to resolve %s as type.", FName(type->UserType->Id).GetChars());
|
||||||
return TypeError;
|
return TypeError;
|
||||||
|
|
|
@ -310,6 +310,7 @@ struct ZCC_BasicType : ZCC_Type
|
||||||
{
|
{
|
||||||
EZCCBuiltinType Type;
|
EZCCBuiltinType Type;
|
||||||
ZCC_Identifier *UserType;
|
ZCC_Identifier *UserType;
|
||||||
|
bool isconst;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZCC_MapType : ZCC_Type
|
struct ZCC_MapType : ZCC_Type
|
||||||
|
|
|
@ -53,7 +53,7 @@ class Actor : Thinker native
|
||||||
return GetPointer(ptr_select1) == GetPointer(ptr_select2);
|
return GetPointer(ptr_select1) == GetPointer(ptr_select2);
|
||||||
}
|
}
|
||||||
|
|
||||||
native static /*readonly*/ Actor GetDefaultByType(class<Actor> cls);
|
native static readonly<Actor> GetDefaultByType(class<Actor> cls);
|
||||||
native void SetDamage(int dmg);
|
native void SetDamage(int dmg);
|
||||||
native static bool isDehState(state st);
|
native static bool isDehState(state st);
|
||||||
native void SetOrigin(vector3 newpos, bool moving);
|
native void SetOrigin(vector3 newpos, bool moving);
|
||||||
|
|
Loading…
Reference in a new issue