From 7cbabfb0d4f28ccbf97850bcfeb72cc35c980aaa Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 5 Mar 2017 01:24:22 +0200 Subject: [PATCH] Implemented implicit 'protected' inheritance in virtual functions --- src/scripting/backend/codegen.cpp | 2 +- src/scripting/vm/vm.h | 15 +++++++-------- src/scripting/vm/vmexec.h | 8 ++++---- src/scripting/vm/vmframe.cpp | 3 +-- src/scripting/zscript/zcc_compile.cpp | 20 ++++++++++++-------- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 1fc243ac3..9f7da15c4 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -8725,7 +8725,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } VMFunction *vmfunc = Function->Variants[0].Implementation; - bool staticcall = (vmfunc->Final || vmfunc->VirtualIndex == ~0u || NoVirtual); + bool staticcall = ((vmfunc->VarFlags & VARF_Final) || vmfunc->VirtualIndex == ~0u || NoVirtual); count = 0; // Emit code to pass implied parameters diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 06de1e2c1..3874df2a7 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -705,10 +705,8 @@ do_double: if (inexact) class VMFunction { public: - bool Native; - bool Final = false; // cannot be overridden - bool Unsafe = false; // Contains references to class fields that are unsafe for psp and item state calls. - bool FuncConst = false; // [ZZ] readonly function + bool Unsafe = false; + int VarFlags = 0; // [ZZ] this replaces 5+ bool fields int BarrierSide = 0; // [ZZ] FScopeBarrier::Side BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action unsigned VirtualIndex = ~0u; @@ -718,7 +716,7 @@ public: class PPrototype *Proto; - VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) + VMFunction(FName name = NAME_None) : ImplicitArgs(0), Name(name), Proto(NULL) { AllFunctions.Push(this); } @@ -942,9 +940,10 @@ class VMNativeFunction : public VMFunction public: typedef int (*NativeCallType)(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret); - VMNativeFunction() : NativeCall(NULL) { Native = true; } - VMNativeFunction(NativeCallType call) : NativeCall(call) { Native = true; } - VMNativeFunction(NativeCallType call, FName name) : VMFunction(name), NativeCall(call) { Native = true; } + // 8 is VARF_Native. + VMNativeFunction() : NativeCall(NULL) { VarFlags = 8; } + VMNativeFunction(NativeCallType call) : NativeCall(call) { VarFlags = 8; } + VMNativeFunction(NativeCallType call, FName name) : VMFunction(name), NativeCall(call) { VarFlags = 8; } // Return value is the number of results. NativeCallType NativeCall; diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index cd3925adc..cdf598649 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -22,7 +22,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) const FVoidObj *konsta; const VM_ATAG *konstatag; - if (f->Func != NULL && !f->Func->Native) + if (f->Func != NULL && !(f->Func->VarFlags & VARF_Native)) { sfunc = static_cast(f->Func); konstd = sfunc->KonstD; @@ -679,7 +679,7 @@ begin: #endif FillReturns(reg, f, returns, pc+1, C); - if (call->Native) + if (call->VarFlags & VARF_Native) { try { @@ -736,7 +736,7 @@ begin: { VMFunction *call = (VMFunction *)ptr; - if (call->Native) + if (call->VarFlags & VARF_Native) { try { @@ -1966,7 +1966,7 @@ static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_ const void *src; VMScriptFunction *func = static_cast(frame->Func); - assert(func != NULL && !func->Native); + assert(func != NULL && !(func->VarFlags & VARF_Native)); assert((regtype & ~REGT_KONST) == ret->RegType); switch (regtype & REGT_TYPE) diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 10fed9abb..44bf46f23 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -48,7 +48,6 @@ TArray VMFunction::AllFunctions; VMScriptFunction::VMScriptFunction(FName name) { - Native = false; Name = name; LineInfo = nullptr; Code = NULL; @@ -438,7 +437,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur bool allocated = false; try { - if (func->Native) + if (func->VarFlags & VARF_Native) { return static_cast(func)->NativeCall(params, func->DefaultArgs, numparams, results, numresults); } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 8a73f891d..533104121 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2416,6 +2416,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool { // [ZZ] unspecified virtual function inherits old scope. virtual function scope can't be changed. sym->Variants[0].Implementation->BarrierSide = FScopeBarrier::SideFromFlags(varflags); + sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags; } PClass *clstype = static_cast(c->Type()); @@ -2426,11 +2427,6 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool Error(f, "Virtual function %s.%s not present", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()); return; } - - if (varflags & VARF_Final) - sym->Variants[0].Implementation->Final = true; - if (varflags & VARF_ReadOnly) - sym->Variants[0].Implementation->FuncConst = true; if (forclass) { @@ -2445,7 +2441,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool else { auto oldfunc = clstype->Virtuals[vindex]; - if (oldfunc->Final) + if (oldfunc->VarFlags & VARF_Final) { Error(f, "Attempt to override final function %s", FName(f->Name).GetChars()); } @@ -2455,19 +2451,27 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool Error(f, "Attempt to change scope for virtual function %s", FName(f->Name).GetChars()); } // you can't change const qualifier for a virtual method - if (sym->Variants[0].Implementation->FuncConst && !oldfunc->FuncConst) + if ((sym->Variants[0].Implementation->VarFlags & VARF_ReadOnly) && !(oldfunc->VarFlags & VARF_ReadOnly)) { Error(f, "Attempt to add const qualifier to virtual function %s", FName(f->Name).GetChars()); } + // you can't change protected qualifier for a virtual method (i.e. putting private), because this cannot be reliably checked without runtime stuff + if (f->Flags & (ZCC_Private | ZCC_Protected)) + { + Error(f, "Attempt to change private/protected qualifiers for virtual function %s", FName(f->Name).GetChars()); + } // inherit scope of original function if override not specified sym->Variants[0].Implementation->BarrierSide = oldfunc->BarrierSide; sym->Variants[0].Flags = FScopeBarrier::ChangeSideInFlags(sym->Variants[0].Flags, oldfunc->BarrierSide); // inherit const from original function - if ((sym->Variants[0].Implementation->FuncConst = oldfunc->FuncConst)) + if (oldfunc->VarFlags & VARF_ReadOnly) sym->Variants[0].Flags |= VARF_ReadOnly; + if (oldfunc->VarFlags & VARF_Protected) + sym->Variants[0].Flags |= VARF_Protected; clstype->Virtuals[vindex] = sym->Variants[0].Implementation; sym->Variants[0].Implementation->VirtualIndex = vindex; + sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags; } } else